+++ /dev/null
-/*
- * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- *
- * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
- * Reserved. This file contains Original Code and/or Modifications of
- * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License"). You may not use this file
- * except in compliance with the License. Please obtain a copy of the
- * License at http://www.apple.com/publicsource and read it before using
- * this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
- * License for the specific language governing rights and limitations
- * under the License.
- *
- * @APPLE_LICENSE_HEADER_END@
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <mach/mach.h>
-#include <servers/bootstrap.h>
-#include <pthread.h>
-#include <errno.h>
-#include <notify.h>
-#include <syslog.h>
-#include <unistd.h>
-#ifdef DEBUG
-#include <asl.h>
-#endif
-#include "lu_utils.h"
-#include "netdb_async.h"
-#include "DSlibinfoMIG.h"
-#include "DSlibinfoMIGAsyncReply.h"
-
-#define MAX_LOOKUP_ATTEMPTS 10
-#define _LU_MAXLUSTRLEN 256
-#define QBUF_SIZE 16384
-#define KVBUF_START_SIZE 128
-
-#define LI_MESSAGE_SEND_ID 4241776
-#define LI_MESSAGE_REPLY_ID 4241876
-
-#define ILS_MAGIC_SIZE 8
-#define ILS_MAGIC "ILSMAGIC"
-
-#define L1_CACHE_NOTIFICATION_KEY_GLOBAL "com.apple.system.DirectoryService.InvalidateCache"
-#define L1_CACHE_NOTIFICATION_KEY_GROUP "com.apple.system.DirectoryService.InvalidateCache.group"
-#define L1_CACHE_NOTIFICATION_KEY_HOST "com.apple.system.DirectoryService.InvalidateCache.host"
-#define L1_CACHE_NOTIFICATION_KEY_SERVICE "com.apple.system.DirectoryService.InvalidateCache.service"
-#define L1_CACHE_NOTIFICATION_KEY_USER "com.apple.system.DirectoryService.InvalidateCache.user"
-
-/* GLOBAL */
-uint32_t gL1CacheEnabled = 1;
-
-static const uint32_t align_32[] = { 0, 1, 2, 0, 4, 0, 0, 0, 4 };
-static const uint32_t align_64[] = { 0, 1, 2, 0, 4, 0, 0, 0, 8 };
-
-static pthread_key_t _info_key = 0;
-static pthread_once_t _info_key_initialized = PTHREAD_ONCE_INIT;
-
-static pthread_mutex_t _notify_lock = PTHREAD_MUTEX_INITIALIZER;
-static int _L1_notify_token[] =
-{
- -1, /* global */
- -1, /* group */
- -1, /* host */
- -1, /* service */
- -1 /* user */
-};
-
-struct _li_data_s
-{
- uint32_t icount;
- uint32_t *ikey;
- void **idata;
-};
-
-typedef struct _li_async_request_s
-{
- mach_port_t reply_port;
- uint32_t retry;
- uint32_t proc;
- void *context;
- void *callback;
- char request[MAX_MIG_INLINE_DATA];
- mach_msg_type_number_t requestCnt;
- char reply[MAX_MIG_INLINE_DATA];
- mach_msg_type_number_t replyCnt;
- vm_address_t ooreply;
- mach_msg_type_number_t ooreplyCnt;
- security_token_t token;
- struct _li_async_request_s *next;
-} _li_async_request_t;
-
-static pthread_mutex_t _li_worklist_lock = PTHREAD_MUTEX_INITIALIZER;
-static _li_async_request_t *_li_worklist = NULL;
-
-/* Send an asynchronous query message. */
-static kern_return_t
-_LI_async_send(_li_async_request_t *r)
-{
- mach_msg_return_t status;
- mach_vm_address_t cb;
-
- if (r == NULL) return KERN_FAILURE;
-
- if (r->retry == 0) return MIG_SERVER_DIED;
- r->retry--;
-
- cb = (mach_vm_address_t)(r->callback);
- status = libinfoDSmig_Query_async(_ds_port, r->reply_port, r->proc, r->request, r->requestCnt, cb);
-
- if (status == MACH_SEND_INVALID_REPLY)
- {
- mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1);
- r->reply_port = MACH_PORT_NULL;
- }
-
- return status;
-}
-
-static _li_async_request_t *
-_LI_worklist_remove(mach_port_t p)
-{
- _li_async_request_t *r, *n;
-
- if (p == MACH_PORT_NULL) return NULL;
- if (_li_worklist == NULL) return NULL;
-
- pthread_mutex_lock(&_li_worklist_lock);
-
- if (_li_worklist->reply_port == p)
- {
- r = _li_worklist;
- _li_worklist = r->next;
- pthread_mutex_unlock(&_li_worklist_lock);
- return r;
- }
-
- for (r = _li_worklist; r != NULL; r = r->next)
- {
- n = r->next;
- if (n == NULL) break;
-
- if (n->reply_port == p)
- {
- r->next = n->next;
- pthread_mutex_unlock(&_li_worklist_lock);
- return n;
- }
- }
-
- pthread_mutex_unlock(&_li_worklist_lock);
- return NULL;
-}
-
-static _li_async_request_t *
-_LI_worklist_find(mach_port_t p)
-{
- _li_async_request_t *r;
-
- if (p == MACH_PORT_NULL) return NULL;
- if (_li_worklist == NULL) return NULL;
-
- pthread_mutex_lock(&_li_worklist_lock);
-
- for (r = _li_worklist; r != NULL; r = r->next)
- {
- if (r->reply_port == p)
- {
- pthread_mutex_unlock(&_li_worklist_lock);
- return r;
- }
- }
-
- pthread_mutex_unlock(&_li_worklist_lock);
- return NULL;
-}
-
-static void
-_LI_free_request(_li_async_request_t *r)
-{
- if (r == NULL) return;
-
- if (r->reply_port != MACH_PORT_NULL) mach_port_mod_refs(mach_task_self(), r->reply_port, MACH_PORT_RIGHT_RECEIVE, -1);
- r->reply_port = MACH_PORT_NULL;
-
- free(r);
-}
-
-/*
- * This is a callback for DSLibinfoMIGAsyncReplyServer.c
- */
-__private_extern__ 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)
-{
- _li_async_request_t *r;
-
- r = _LI_worklist_find(server);
-
- if (r != NULL)
- {
- r->ooreply = ooreply;
- r->ooreplyCnt = ooreplyCnt;
- if (replyCnt > 0) memcpy(r->reply, reply, replyCnt);
- r->replyCnt = replyCnt;
- r->token = servertoken;
- }
- else if (ooreplyCnt != 0)
- {
- vm_deallocate(mach_task_self(), ooreply, ooreplyCnt);
- }
-
- return KERN_SUCCESS;
-}
-
-/* Receive an asynchronous reply message. */
-kern_return_t
-LI_async_receive(mach_port_t p, kvarray_t **reply)
-{
- kern_return_t status;
- _li_async_request_t *r;
- kvbuf_t *out;
- int flags;
-
- flags = MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
-
- /* use mach_msg_server_once to do the work here */
- status = mach_msg_server_once(DSlibinfoMIGAsyncReply_server, 65536, p, flags);
-
- if (status != KERN_SUCCESS) return status;
-
- r = _LI_worklist_remove(p);
- if (r == NULL) return KERN_FAILURE;
-
- out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
- if (out == NULL)
- {
- if (r->ooreplyCnt > 0) vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt);
- return KERN_FAILURE;
- }
-
- if (r->ooreplyCnt > 0)
- {
- out->datalen = r->ooreplyCnt;
- out->databuf = malloc(r->ooreplyCnt);
- if (out->databuf == NULL)
- {
- free(out);
- *reply = NULL;
- vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt);
- return KERN_FAILURE;
- }
-
- memcpy(out->databuf, (char *)r->ooreply, r->ooreplyCnt);
- vm_deallocate(mach_task_self(), r->ooreply, r->ooreplyCnt);
- }
- else if (r->replyCnt > 0)
- {
- out->datalen = r->replyCnt;
- out->databuf = malloc(r->replyCnt);
- if (out->databuf == NULL)
- {
- free(out);
- *reply = NULL;
- return KERN_FAILURE;
- }
-
- memcpy(out->databuf, r->reply, r->replyCnt);
- }
-
- *reply = kvbuf_decode(out);
- if (*reply == NULL)
- {
- /* DS returned no data */
- free(out->databuf);
- free(out);
- }
-
- _LI_free_request(r);
-
- return KERN_SUCCESS;
-}
-
-static void
-_LI_worklist_append(_li_async_request_t *r)
-{
- _li_async_request_t *p;
-
- if (r == NULL) return;
-
- pthread_mutex_lock(&_li_worklist_lock);
-
- if (_li_worklist == NULL)
- {
- _li_worklist = r;
- pthread_mutex_unlock(&_li_worklist_lock);
- return;
- }
-
- for (p = _li_worklist; p->next != NULL; p = p->next);
- p->next = r;
-
- pthread_mutex_unlock(&_li_worklist_lock);
-}
-
-void
-LI_async_call_cancel(mach_port_t p, void **context)
-{
- _li_async_request_t *req;
-
- req = _LI_worklist_remove(p);
-
- if (req != NULL)
- {
- if (context != NULL) *context = req->context;
- _LI_free_request(req);
- }
- else if (p != MACH_PORT_NULL)
- {
- mach_port_mod_refs(mach_task_self(), p, MACH_PORT_RIGHT_RECEIVE, -1);
- }
-}
-
-void
-lu_async_call_cancel(mach_port_t p)
-{
- LI_async_call_cancel(p, NULL);
-}
-
-static _li_async_request_t *
-_LI_create_request(uint32_t proc, kvbuf_t *query, void *callback, void *context)
-{
- _li_async_request_t *r;
- kern_return_t status;
- mach_port_t target;
-
- if (_ds_running() == 0) return NULL;
- if (query == NULL) return NULL;
- if (query->datalen > MAX_MIG_INLINE_DATA) return NULL;
-
- r = (_li_async_request_t *)calloc(1, sizeof(_li_async_request_t));
- if (r == NULL) return NULL;
-
- status = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &(r->reply_port));
- if (status != KERN_SUCCESS)
- {
- _LI_free_request(r);
- return NULL;
- }
-
- target = MACH_PORT_NULL;
-
- /* Request no-senders notification so we can tell when server dies */
- mach_port_request_notification(mach_task_self(), r->reply_port, MACH_NOTIFY_NO_SENDERS, 1, r->reply_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &target);
-
- r->retry = MAX_LOOKUP_ATTEMPTS;
-
- r->context = context;
- r->callback = callback;
- r->proc = proc;
-
- memcpy(r->request, query->databuf, query->datalen);
- r->requestCnt = query->datalen;
-
- r->next = NULL;
-
- return r;
-}
-
-kern_return_t
-LI_async_start(mach_port_t *p, uint32_t proc, kvbuf_t *query, void *callback, void *context)
-{
- _li_async_request_t *r;
- kern_return_t status;
- uint32_t retry;
-
- if (p == NULL) return KERN_FAILURE;
-
- *p = MACH_PORT_NULL;
-
- if (_ds_running() == 0) return KERN_FAILURE;
- if (_ds_port == MACH_PORT_NULL) return KERN_FAILURE;
-
- /* Make a request struct to keep track */
- r = _LI_create_request(proc, query, callback, context);
- if (r == NULL) return KERN_FAILURE;
-
- status = MIG_SERVER_DIED;
- for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++)
- {
- status = _LI_async_send(r);
- }
-
- if (status != KERN_SUCCESS)
- {
- _LI_free_request(r);
- return status;
- }
-
- /* Add request to worklist */
- _LI_worklist_append(r);
-
- *p = r->reply_port;
-
- return KERN_SUCCESS;
-}
-
-kern_return_t
-LI_async_send(mach_port_t *p, uint32_t proc, kvbuf_t *query)
-{
- return LI_async_start(p, proc, query, NULL, NULL);
-}
-
-kern_return_t
-LI_async_handle_reply(mach_msg_header_t *msg, kvarray_t **reply, void **callback, void **context)
-{
- _li_async_request_t *req;
- kvbuf_t *out;
- kern_return_t status;
- uint32_t retry;
- mig_reply_error_t *bufReply;
-
- if (msg == NULL) return -1;
-
- /* If reply status was an error, resend */
- if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS)
- {
- /* if server died */
- req = _LI_worklist_find(msg->msgh_local_port);
- if (req == NULL) return -1;
-
- status = MIG_SERVER_DIED;
- for (retry = 0; (status == MIG_SERVER_DIED) && (retry < MAX_LOOKUP_ATTEMPTS); retry++)
- {
- /* send message */
- status = _LI_async_send(req);
- }
-
- if (status != KERN_SUCCESS) return -1;
-
- return MIG_REPLY_MISMATCH;
- }
-
- /* need to implement the msg_server_once type code here */
- mach_msg_size_t reply_alloc = round_page(65536 + MAX_TRAILER_SIZE);
-
- status = vm_allocate(mach_task_self(), (vm_address_t *) &bufReply, reply_alloc, VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | TRUE);
- if (status != KERN_SUCCESS) return status;
-
- status = DSlibinfoMIGAsyncReply_server(msg, (mach_msg_header_t *)bufReply);
-
- /* we just destroy the reply, because there isn't one */
- if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) mach_msg_destroy(&bufReply->Head);
-
- vm_deallocate(mach_task_self(), (vm_address_t) bufReply, reply_alloc);
-
- if (status == FALSE) return KERN_FAILURE;
-
- req = _LI_worklist_remove(msg->msgh_local_port);
- if (req == NULL) return KERN_FAILURE;
-
- *callback = req->callback;
- *context = req->context;
-
- out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
- if (out == NULL)
- {
- if (req->ooreplyCnt > 0) vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt);
- return KERN_FAILURE;
- }
-
- if (req->ooreplyCnt > 0)
- {
- out->datalen = req->ooreplyCnt;
- out->databuf = malloc(req->ooreplyCnt);
- if (out->databuf == NULL)
- {
- free(out);
- *reply = NULL;
- vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt);
- return KERN_FAILURE;
- }
-
- memcpy(out->databuf, (char *)req->ooreply, req->ooreplyCnt);
- vm_deallocate(mach_task_self(), req->ooreply, req->ooreplyCnt);
- }
- else if (req->replyCnt > 0)
- {
- out->datalen = req->replyCnt;
- out->databuf = malloc(req->replyCnt);
- if (out->databuf == NULL)
- {
- free(out);
- *reply = NULL;
- return KERN_FAILURE;
- }
-
- memcpy(out->databuf, req->reply, req->replyCnt);
- }
-
- *reply = kvbuf_decode(out);
- if (*reply == NULL)
- {
- /* DS returned no data */
- free(out->databuf);
- free(out);
- }
-
- _LI_free_request(req);
-
- return KERN_SUCCESS;
-}
-
-static void
-_LI_thread_info_free(void *x)
-{
- struct li_thread_info *tdata;
-
- if (x == NULL) return;
-
- tdata = (struct li_thread_info *)x;
- LI_ils_free(tdata->li_entry, tdata->li_entry_size);
- LI_data_free_kvarray(tdata);
-
- free(tdata);
-}
-
-static void
-_LI_data_free(void *x)
-{
- struct _li_data_s *t;
- int i;
-
- if (x == NULL) return;
-
- t = (struct _li_data_s *)x;
-
- for (i = 0; i < t->icount; i++)
- {
- _LI_thread_info_free(t->idata[i]);
- t->idata[i] = NULL;
- }
-
- if (t->ikey != NULL) free(t->ikey);
- t->ikey = NULL;
-
- if (t->idata != NULL) free(t->idata);
- t->idata = NULL;
-
- free(t);
-}
-
-static void
-_LI_data_init()
-{
- pthread_key_create(&_info_key, _LI_data_free);
- return;
-}
-
-static struct _li_data_s *
-_LI_data_get()
-{
- struct _li_data_s *libinfo_data;
-
- /*
- * Only one thread should create the _info_key
- */
- pthread_once(&_info_key_initialized, _LI_data_init);
-
- /* Check if this thread already created libinfo_data */
- libinfo_data = pthread_getspecific(_info_key);
- if (libinfo_data != NULL) return libinfo_data;
-
- libinfo_data = (struct _li_data_s *)calloc(1, sizeof(struct _li_data_s));
- if (libinfo_data == NULL) return NULL;
-
- pthread_setspecific(_info_key, libinfo_data);
- return libinfo_data;
-}
-
-__private_extern__ void *
-LI_data_find_key(uint32_t key)
-{
- struct _li_data_s *libinfo_data;
- uint32_t i;
-
- libinfo_data = _LI_data_get();
- if (libinfo_data == NULL) return NULL;
-
- for (i = 0; i < libinfo_data->icount; i++)
- {
- if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i];
- }
-
- return NULL;
-}
-
-__private_extern__ void *
-LI_data_create_key(uint32_t key, size_t esize)
-{
- struct _li_data_s *libinfo_data;
- struct li_thread_info *tdata;
- uint32_t i, n;
-
- libinfo_data = _LI_data_get();
- if (libinfo_data == NULL) return NULL;
-
- for (i = 0; i < libinfo_data->icount; i++)
- {
- if (libinfo_data->ikey[i] == key) return libinfo_data->idata[i];
- }
-
- i = libinfo_data->icount;
- n = i + 1;
-
- if (i == 0)
- {
- libinfo_data->ikey = (uint32_t *)malloc(sizeof(uint32_t));
- libinfo_data->idata = (void **)malloc(sizeof(void *));
- }
- else
- {
- libinfo_data->ikey = (uint32_t *)reallocf(libinfo_data->ikey, n * sizeof(uint32_t));
- libinfo_data->idata = (void **)reallocf(libinfo_data->idata, n * sizeof(void *));
- }
-
- if ((libinfo_data->ikey == NULL) || (libinfo_data->idata == NULL))
- {
- if (libinfo_data->ikey != NULL) free(libinfo_data->ikey);
- libinfo_data->ikey = NULL;
-
- if (libinfo_data->idata != NULL) free(libinfo_data->idata);
- libinfo_data->idata = NULL;
-
- return NULL;
- }
-
- tdata = (struct li_thread_info *)calloc(1, sizeof(struct li_thread_info));
- if (tdata == NULL) return NULL;
-
- tdata->li_entry_size = esize;
-
- libinfo_data->ikey[i] = key;
- libinfo_data->idata[i] = tdata;
- libinfo_data->icount++;
-
- return tdata;
-}
-
-static uint32_t
-_LI_data_index(uint32_t key, struct _li_data_s *libinfo_data)
-{
- uint32_t i;
-
- if (libinfo_data == NULL) return (uint32_t)-1;
-
- for (i = 0; i < libinfo_data->icount; i++)
- {
- if (libinfo_data->ikey[i] == key) return i;
- }
-
- return (uint32_t)-1;
-}
-
-void
-_LI_data_set_key(uint32_t key, void *data)
-{
- struct _li_data_s *libinfo_data;
- uint32_t i;
-
- libinfo_data = _LI_data_get();
- if (libinfo_data == NULL) return;
-
- i = _LI_data_index(key, libinfo_data);
- if (i == (uint32_t)-1) return;
-
- libinfo_data->idata[i] = data;
-}
-
-void *
-_LI_data_get_key(uint32_t key)
-{
- struct _li_data_s *libinfo_data;
- uint32_t i;
-
- libinfo_data = _LI_data_get();
- if (libinfo_data == NULL) return NULL;
-
- i = _LI_data_index(key, libinfo_data);
- if (i == (uint32_t)-1) return NULL;
-
- return libinfo_data->idata[i];
-}
-
-__private_extern__ void
-LI_data_free_kvarray(struct li_thread_info *tdata)
-{
- if (tdata == NULL) return;
- if (tdata->li_vm == NULL) return;
-
- kvarray_free((kvarray_t *)tdata->li_vm);
- tdata->li_vm = NULL;
-}
-
-__private_extern__ void
-LI_data_recycle(struct li_thread_info *tdata, void *entry, size_t entrysize)
-{
- if (tdata == NULL) return;
-
- LI_ils_free(tdata->li_entry, entrysize);
- tdata->li_entry = entry;
-}
-
-#define KVBUF_CHUNK 256
-
-/*
- * kvbuf_t is a list of key/value dictionaries.
- *
- * First 4 bytes are the number of dictionaries.
- * For each dictionary, first 4 bytes is the key / value list count.
- * For each value list, first 4 bytes is the list length.
- * Keys and values are a 4-byte length followed by a nul-terminated string
- *
- * When the databuf needs to grow, we add memory in KVBUF_CHUNK size
- * increments to reduce malloc / realloc activity.
- * The _size variable stores the actual allocated size.
- * The datalen variable stores the used data size.
- *
- * The _dict variable holds an offset from the start of the buffer
- * to the "current" dictionary. kvbuf_reset() resets this,
- * and kvbuf_next_dict() bumps the offset so that databuf + _dict
- * points to the next dictionary.
- *
- * The _key variable holds an offset from the start of the buffer
- * to the "current" key. kvbuf_reset() resets this, and
- * kvbuf_next_key() bumps the offset so that databuf + _key
- * points to the next key.
- *
- * The _val variable holds an offset from the start of the buffer
- * to the "current" value. kvbuf_reset() resets this, and
- * kvbuf_next_val() bumps the offset so that databuf + _val
- * points to the next value.
- *
- * The cache_entry_list_to_kvbuf() routine contains the only
- * code that builds an array.
- *
- */
-
-/*
- * kvbuf_query is a simple utility for constructing a
- * kvbuf with a single dictionary. The format string may
- * contain the chars "k", "s", "i", and "u". "k" denotes a key
- * (keys are always strings), "s" denotes a string value,
- * "i" denotes a 32 bit signed int, and "u" denotes an unsigned.
- */
-__private_extern__ kvbuf_t *
-kvbuf_query(char *fmt, ...)
-{
- va_list ap;
- char *arg, *f, str[32];
- int32_t iarg;
- uint32_t uarg;
- kvbuf_t *kv;
-
- if (fmt == NULL) return NULL;
-
- kv = kvbuf_new();
- if (kv == NULL) return NULL;
-
- kvbuf_add_dict(kv);
-
- va_start(ap, fmt);
- for (f = fmt; (*f) != '\0'; f++)
- {
- if (*f == 'k')
- {
- arg = va_arg(ap, char *);
- kvbuf_add_key(kv, arg);
- }
- else if (*f == 's')
- {
- arg = va_arg(ap, char *);
- kvbuf_add_val(kv, arg);
- }
- else if (*f == 'i')
- {
- iarg = va_arg(ap, int32_t);
- snprintf(str, sizeof(str), "%d", iarg);
- kvbuf_add_val(kv, str);
- }
- else if (*f == 'u')
- {
- uarg = va_arg(ap,uint32_t);
- snprintf(str, sizeof(str), "%u", uarg);
- kvbuf_add_val(kv, str);
- }
- }
- va_end(ap);
-
- return kv;
-}
-
-__private_extern__ kvbuf_t *
-kvbuf_query_key_val(const char *key, const char *val)
-{
- kvbuf_t *kv;
- uint32_t x, kl, vl, vc;
- char *p;
-
- if (key == NULL) return NULL;
-
- kl = strlen(key) + 1;
-
- vl = 0;
- vc = 0;
-
- if (val != NULL)
- {
- vl = strlen(val) + 1;
- vc = 1;
- }
-
- kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
- if (kv == NULL) return NULL;
-
- kv->_size = (5 * sizeof(uint32_t)) + kl + vl;
- kv->datalen = kv->_size;
-
- kv->databuf = calloc(1, kv->_size);
- if (kv->databuf == NULL)
- {
- free(kv);
- return NULL;
- }
-
- p = kv->databuf;
-
- /* 1 dict */
- x = htonl(1);
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
-
- /* 1 key */
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
-
- /* key length */
- x = htonl(kl);
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
-
- /* key */
- memcpy(p, key, kl);
- p += kl;
-
- /* number of values */
- x = htonl(vc);
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
-
- if (vc > 0)
- {
- /* value length */
- x = htonl(vl);
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
-
- /* value */
- memcpy(p, val, vl);
- }
-
- return kv;
-}
-
-__private_extern__ kvbuf_t *
-kvbuf_query_key_int(const char *key, int32_t i)
-{
- char str[32];
-
- snprintf(str, sizeof(str), "%d", i);
- return kvbuf_query_key_val(key, str);
-}
-
-__private_extern__ kvbuf_t *
-kvbuf_query_key_uint(const char *key, uint32_t u)
-{
- char str[32];
-
- snprintf(str, sizeof(str), "%u", u);
- return kvbuf_query_key_val(key, str);
-}
-
-kvbuf_t *
-kvbuf_new(void)
-{
- kvbuf_t *kv;
-
- kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
- if (kv == NULL) return NULL;
-
- kv->_size = KVBUF_START_SIZE;
- kv->databuf = calloc(1, kv->_size);
- if (kv->databuf == NULL)
- {
- free(kv);
- return NULL;
- }
-
- kv->datalen = sizeof(uint32_t);
- kv->_dict = kv->datalen;
-
- return kv;
-}
-
-kvbuf_t *
-kvbuf_init(char *buffer, uint32_t length)
-{
- kvbuf_t *kv;
-
- kv = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
- if (kv == NULL) return NULL;
-
- kv->_size = length;
- kv->datalen = length;
- kv->databuf = calloc(1, length);
- if (kv->databuf == NULL)
- {
- free(kv);
- kv = NULL;
- }
- else
- {
- memcpy(kv->databuf, buffer, length);
- }
-
- return kv;
-}
-
-static void
-kvbuf_grow(kvbuf_t *kv, uint32_t delta)
-{
- uint32_t newlen, n;
- char *p;
-
- if (kv == NULL) return;
- if (delta == 0) return;
-
- if (kv->databuf == NULL) delta += sizeof(uint32_t);
-
- n = (delta + KVBUF_CHUNK - 1) / KVBUF_CHUNK;
- newlen = kv->datalen + (n * KVBUF_CHUNK);
-
- if (newlen <= kv->_size) return;
-
- kv->_size = newlen;
-
- if (kv->databuf == NULL)
- {
- kv->databuf = calloc(1, kv->_size);
- if (kv->databuf == NULL)
- {
- memset(kv, 0, sizeof(kvbuf_t));
- return;
- }
-
- kv->datalen = sizeof(uint32_t);
- kv->_dict = sizeof(uint32_t);
- }
- else
- {
- kv->databuf = reallocf(kv->databuf, kv->_size);
- if (kv->databuf == NULL)
- {
- memset(kv, 0, sizeof(kvbuf_t));
- return;
- }
-
- p = kv->databuf + kv->datalen;
- memset(p, 0, kv->_size - kv->datalen);
- }
-}
-
-void
-kvbuf_add_dict(kvbuf_t *kv)
-{
- char *p;
- uint32_t x, dict_count;
-
- if (kv == NULL) return;
-
- /* Add a key count */
- kvbuf_grow(kv, sizeof(uint32_t));
- if (kv->databuf == NULL) return;
-
- kv->_dict = kv->datalen;
- kv->datalen += sizeof(uint32_t);
-
- kv->_key = kv->datalen;
- kv->_vlist = 0;
- kv->_val = 0;
-
- /* increment and rewrite the dict count */
- p = kv->databuf;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- dict_count = ntohl(x);
-
- dict_count++;
- x = htonl(dict_count);
- memcpy(p, &x, sizeof(uint32_t));
-}
-
-void
-kvbuf_add_key(kvbuf_t *kv, const char *key)
-{
- uint32_t kl, x, key_count, delta;
- char *p;
-
- if (kv == NULL) return;
- if (key == NULL) return;
-
- kl = strlen(key) + 1;
-
- /* Grow to hold key len, key, and value list count. */
- delta = (2 * sizeof(uint32_t)) + kl;
- kvbuf_grow(kv, delta);
-
- if (kv->databuf == NULL) return;
-
- /* increment and rewrite the key count for the current dictionary */
- p = kv->databuf + kv->_dict;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- key_count = ntohl(x);
-
- if (key_count == 0) kv->_key = kv->_dict + sizeof(uint32_t);
- else kv->_key = kv->datalen;
-
- key_count++;
- x = htonl(key_count);
- memcpy(p, &x, sizeof(uint32_t));
-
- /* append key to data buffer */
- p = kv->databuf + kv->datalen;
-
- x = htonl(kl);
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
- memcpy(p, key, kl);
- p += kl;
-
- kv->_vlist = kv->datalen + sizeof(uint32_t) + kl;
-
- x = 0;
- memcpy(p, &x, sizeof(uint32_t));
-
- kv->datalen += delta;
- kv->_val = kv->datalen;
-}
-
-void
-kvbuf_add_val_len(kvbuf_t *kv, const char *val, uint32_t len)
-{
- uint32_t x, val_count, delta;
- char *p;
-
- if (kv == NULL) return;
- if (val == NULL) return;
- if (len == 0) return;
-
- /* Grow to hold val len and value. */
- delta = sizeof(uint32_t) + len;
- kvbuf_grow(kv, delta);
-
- if (kv->databuf == NULL) return;
-
- /* increment and rewrite the value count for the value_list dictionary */
- p = kv->databuf + kv->_vlist;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- val_count = ntohl(x);
- val_count++;
- x = htonl(val_count);
- memcpy(p, &x, sizeof(uint32_t));
-
- /* append val to data buffer */
- p = kv->databuf + kv->_val;
-
- x = htonl(len);
- memcpy(p, &x, sizeof(uint32_t));
- p += sizeof(uint32_t);
- memcpy(p, val, len);
- p += len;
-
- kv->datalen += delta;
- kv->_val = kv->datalen;
-}
-
-/*
- * WARNING! Kludge Alert!
- *
- * This call just looks for the buffer length encoded into a serialized kvbuf_t,
- * which preceeds a pointer to a key or value. Obviously, calling it with anything
- * other than a pointer value which is embedded in a kvbuf_t is asking for trouble.
- */
-uint32_t
-kvbuf_get_len(const char *p)
-{
- uint32_t x;
-
- x = 0;
- memcpy(&x, p - sizeof(uint32_t), sizeof(uint32_t));
- return ntohl(x);
-}
-
-void
-kvbuf_add_val(kvbuf_t *kv, const char *val)
-{
- if (kv == NULL) return;
- if (val == NULL) return;
-
- kvbuf_add_val_len(kv, val, strlen(val) + 1);
-}
-
-void
-kvbuf_free(kvbuf_t *kv)
-{
- if (kv == NULL) return;
- if (kv->databuf != NULL) free(kv->databuf);
- memset(kv, 0, sizeof(kvbuf_t));
- free(kv);
-}
-
-/* appends a kvbuf to an existing kvbuf */
-void
-kvbuf_append_kvbuf(kvbuf_t *kv, const kvbuf_t *kv2)
-{
- uint32_t curr_count, new_count, temp;
-
- if (kv == NULL) return;
- if (kv2 == NULL) return;
-
- curr_count = 0;
- new_count = 0;
-
- memcpy(&temp, kv->databuf, sizeof(uint32_t));
- curr_count = ntohl(temp);
-
- memcpy(&temp, kv2->databuf, sizeof(uint32_t));
- new_count = ntohl(temp);
-
- /* nothing to do */
- if (new_count == 0) return;
-
- /* add the dictionary count to the current dictionary counts */
- curr_count += new_count;
-
- temp = htonl(curr_count);
- memcpy(kv->databuf, &temp, sizeof(uint32_t));
-
- /* grow the current buffer so we can append the new buffer */
- temp = kv2->datalen - sizeof(uint32_t);
-
- kvbuf_grow(kv, temp);
-
- memcpy(kv->databuf + kv->datalen, kv2->databuf + sizeof(uint32_t), temp);
- kv->datalen += temp;
-}
-
-/* returns number of dictionaries */
-uint32_t
-kvbuf_reset(kvbuf_t *kv)
-{
- uint32_t x;
-
- if (kv == NULL) return 0;
- if (kv->databuf == NULL) return 0;
-
- kv->_dict = 0;
- kv->_key = 0;
- kv->_vlist = 0;
- kv->_val = 0;
-
- if (kv->datalen < sizeof(uint32_t)) return 0;
-
- x = 0;
- memcpy(&x, kv->databuf, sizeof(uint32_t));
- return ntohl(x);
-}
-
-/* advance to next dictionary, returns key count */
-uint32_t
-kvbuf_next_dict(kvbuf_t *kv)
-{
- uint32_t x, k, v, kcount, vcount, kl, vl;
- char *p;
-
- if (kv == NULL) return 0;
- if (kv->databuf == NULL) return 0;
-
- kv->_key = 0;
- kv->_vlist = 0;
- kv->_val = 0;
-
- if (kv->_dict == 0)
- {
- /* first dict */
- if (kv->datalen < sizeof(uint32_t)) return 0;
- kv->_dict = sizeof(uint32_t);
-
- if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0;
-
- p = kv->databuf + kv->_dict;
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- kcount = ntohl(x);
-
- return kcount;
- }
-
- p = kv->databuf + kv->_dict;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_dict += sizeof(uint32_t);
- kcount = ntohl(x);
-
- for (k = 0; k < kcount; k++)
- {
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_dict += sizeof(uint32_t);
- kl = ntohl(x);
- p += kl;
- kv->_dict += kl;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_dict += sizeof(uint32_t);
- vcount = ntohl(x);
-
- for (v = 0; v < vcount; v++)
- {
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_dict += sizeof(uint32_t);
- vl = ntohl(x);
- p += vl;
- kv->_dict += vl;
- }
- }
-
- if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return 0;
-
- p = kv->databuf + kv->_dict;
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- kcount = ntohl(x);
-
- return kcount;
-}
-
-/* advance to next key, returns key and sets val_count */
-char *
-kvbuf_next_key(kvbuf_t *kv, uint32_t *val_count)
-{
- uint32_t x, kl, v, vl, vc;
- char *p, *out;
-
- if (kv == NULL) return NULL;
- if (val_count == NULL) return NULL;
-
- *val_count = 0;
-
- if (kv->databuf == NULL) return NULL;
- if (kv->_dict == 0) return NULL;
-
- kv->_vlist = 0;
- kv->_val = 0;
-
- if (kv->_key == 0)
- {
- /* first key */
- if (kv->datalen < (kv->_dict + sizeof(uint32_t))) return NULL;
- kv->_key = kv->_dict + sizeof(uint32_t);
- }
- else
- {
- p = kv->databuf + kv->_key;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- kl = ntohl(x);
-
- if (kv->datalen < (kv->_key + sizeof(uint32_t) + kl)) return NULL;
-
- p += (sizeof(uint32_t) + kl);
- kv->_key += (sizeof(uint32_t) + kl);
-
- /* skip over values */
- if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- vc = ntohl(x);
-
- p += sizeof(uint32_t);
- kv->_key += sizeof(uint32_t);
-
- for (v = 0; v < vc; v++)
- {
- if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL;
-
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- vl = ntohl(x);
-
- if (kv->datalen < (kv->_key + kl)) return NULL;
-
- p += (sizeof(uint32_t) + vl);
- kv->_key += (sizeof(uint32_t) + vl);
- }
- }
-
- if (kv->datalen < (kv->_key + sizeof(uint32_t))) return NULL;
-
- p = kv->databuf + kv->_key;
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- kl = ntohl(x);
-
- p += sizeof(uint32_t);
- out = p;
-
- kv->_vlist = kv->_key + sizeof(uint32_t) + kl;
- if (kv->datalen < (kv->_vlist + sizeof(uint32_t)))
- {
- kv->_vlist = 0;
- return NULL;
- }
-
- p = kv->databuf + kv->_vlist;
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- *val_count = ntohl(x);
-
- return out;
-}
-
-char *
-kvbuf_next_val(kvbuf_t *kv)
-{
- return kvbuf_next_val_len(kv, NULL);
-}
-
-char *
-kvbuf_next_val_len(kvbuf_t *kv, uint32_t *len)
-{
- uint32_t x = 0;
- uint32_t vltemp = 0;
- char *p;
-
- if (kv == NULL) return NULL;
- if (kv->databuf == NULL) return NULL;
- if (kv->_vlist == 0) return NULL;
-
- if (kv->_val == 0)
- {
- /* first val */
- if (kv->datalen < (kv->_vlist + sizeof(uint32_t))) return NULL;
- kv->_val = kv->_vlist + sizeof(uint32_t);
-
- p = kv->databuf + kv->_val;
-
- memcpy(&x, p, sizeof(uint32_t));
- vltemp = ntohl(x);
- }
- else
- {
- p = kv->databuf + kv->_val;
-
- memcpy(&x, p, sizeof(uint32_t));
- vltemp = ntohl(x);
-
- if (kv->datalen < (kv->_val + sizeof(uint32_t) + vltemp)) return NULL;
-
- p += (sizeof(uint32_t) + vltemp);
- kv->_val += (sizeof(uint32_t) + vltemp);
- }
-
- if (kv->datalen < (kv->_val + sizeof(uint32_t))) return NULL;
-
- if (len != NULL) (*len) = vltemp;
- p = kv->databuf + kv->_val + sizeof(uint32_t);
- return p;
-}
-
-/*
- * Builds a kvarray_t / kvdict_t structure on top of a kvbuf_t.
- * It allocates the appropriate number of kvdict_t structures
- * for the array, sets all the counters, and fills in pointers
- * for keys and valuse. The pointers are NOT to newly allocated
- * strings: they just point into the kvbuf data buffer.
- *
- * To dispose of the kvarray_t and all of the associated
- * memory AND to free the original kvbuf, clients only
- * need to call kvarray_free().
- */
-kvarray_t *
-kvbuf_decode(kvbuf_t *kv)
-{
- kvarray_t *a;
- uint32_t x, d, k, v;
- char *p;
-
- if (kv == NULL) return NULL;
- if (kv->databuf == NULL) return NULL;
-
- if (kv->datalen < sizeof(uint32_t)) return NULL;
-
- p = kv->databuf;
- kv->_size = kv->datalen;
-
- /* array count */
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_size -= sizeof(uint32_t);
- x = ntohl(x);
-
- if (x == 0) return NULL;
-
- a = (kvarray_t *)calloc(1, sizeof(kvarray_t));
- if (a == NULL) return NULL;
-
- a->count = x;
- a->dict = (kvdict_t *)calloc(a->count, sizeof(kvdict_t));
- if (a->dict == NULL)
- {
- free(a);
- return NULL;
- }
-
- for (d = 0; d < a->count; d++)
- {
- if (kv->_size < sizeof(uint32_t))
- {
- kvarray_free(a);
- return NULL;
- }
-
- /* key count */
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_size -= sizeof(uint32_t);
- a->dict[d].kcount = ntohl(x);
-
- if (a->dict[d].kcount > 0)
- {
- a->dict[d].key = (const char **)calloc(a->dict[d].kcount, sizeof(const char *));
- if (a->dict[d].key == NULL)
- {
- kvarray_free(a);
- return NULL;
- }
-
- a->dict[d].vcount = (uint32_t *)calloc(a->dict[d].kcount, sizeof(uint32_t));
- if (a->dict[d].vcount == NULL)
- {
- kvarray_free(a);
- return NULL;
- }
-
- a->dict[d].val = (const char ***)calloc(a->dict[d].kcount, sizeof(char **));
- if (a->dict[d].val == NULL)
- {
- kvarray_free(a);
- return NULL;
- }
- }
-
- for (k = 0; k < a->dict[d].kcount; k++)
- {
- /* get key */
- if (kv->_size < sizeof(uint32_t))
- {
- kvarray_free(a);
- return NULL;
- }
-
- /* key length */
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_size -= sizeof(uint32_t);
- x = ntohl(x);
-
- if (kv->_size < x)
- {
- kvarray_free(a);
- return NULL;
- }
-
- /* key data */
- a->dict[d].key[k] = p;
-
- p += x;
- kv->_size -= x;
-
- if (kv->_size < sizeof(uint32_t))
- {
- kvarray_free(a);
- return NULL;
- }
-
- /* val count */
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_size -= sizeof(uint32_t);
- a->dict[d].vcount[k] = ntohl(x);
-
- if (a->dict[d].vcount[k] > 0)
- {
- /* N.B. we add a NULL pointer at the end of the list */
- a->dict[d].val[k] = (const char **)calloc(a->dict[d].vcount[k] + 1, sizeof(const char *));
- if (a->dict[d].val[k] == NULL)
- {
- kvarray_free(a);
- return NULL;
- }
- }
-
- for (v = 0; v < a->dict[d].vcount[k]; v++)
- {
- /* get val */
- if (kv->_size < sizeof(uint32_t))
- {
- kvarray_free(a);
- return NULL;
- }
-
- /* val length */
- x = 0;
- memcpy(&x, p, sizeof(uint32_t));
- p += sizeof(uint32_t);
- kv->_size -= sizeof(uint32_t);
- x = ntohl(x);
-
- if (kv->_size < x)
- {
- kvarray_free(a);
- return NULL;
- }
-
- /* val data */
- a->dict[d].val[k][v] = p;
-
- p += x;
- kv->_size -= x;
- }
- }
- }
-
- a->kv = kv;
- return a;
-}
-
-void
-kvarray_free(kvarray_t *a)
-{
- uint32_t d, k;
-
- if (a == NULL) return;
-
- for (d = 0; d < a->count; d++)
- {
- for (k = 0; k < a->dict[d].kcount; k++)
- {
- if (a->dict[d].val == NULL) continue;
- if (a->dict[d].val[k] != NULL) free(a->dict[d].val[k]);
- }
-
- if (a->dict[d].key != NULL) free(a->dict[d].key);
- if (a->dict[d].vcount != NULL) free(a->dict[d].vcount);
- if (a->dict[d].val != NULL) free(a->dict[d].val);
- }
-
- a->count = 0;
-
- if (a->dict != NULL) free(a->dict);
- a->dict = NULL;
-
- if (a->kv != NULL) kvbuf_free(a->kv);
- a->kv = NULL;
-
- free(a);
-}
-
-kern_return_t
-LI_DSLookupGetProcedureNumber(const char *name, int32_t *procno)
-{
- 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;
-
- 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++)
- {
- status = libinfoDSmig_GetProcedureNumber(_ds_port, (char *)name, procno, &token);
-
- if (status == MACH_SEND_INVALID_DEST)
- {
- mach_port_mod_refs(mach_task_self(), _ds_port, MACH_PORT_RIGHT_SEND, -1);
- status = bootstrap_look_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port);
- if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
- status = MIG_SERVER_DIED;
- }
- }
-
- if (status != KERN_SUCCESS)
- {
-#ifdef DEBUG
- asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s status %u", name, status);
-#endif
- return status;
- }
-
- 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;
- }
-
-#ifdef DEBUG
- asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupGetProcedureNumber %s = %d", name, *procno);
-#endif
- return status;
-}
-
-__private_extern__ kern_return_t
-LI_DSLookupQuery(int32_t procno, kvbuf_t *request, kvarray_t **reply)
-{
- 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;
-
- 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_up(bootstrap_port, kDSStdMachDSLookupPortName, &_ds_port);
- if ((status != BOOTSTRAP_SUCCESS) && (status != BOOTSTRAP_UNKNOWN_SERVICE)) _ds_port = MACH_PORT_NULL;
- status = MIG_SERVER_DIED;
- }
- }
-
- if (status != KERN_SUCCESS)
- {
-#ifdef DEBUG
- asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status %u", procno, status);
-#endif
- return status;
- }
-
- 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) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen);
- return KERN_FAILURE;
- }
-
- out = (kvbuf_t *)calloc(1, sizeof(kvbuf_t));
- if (out == NULL)
- {
- if (oolen > 0) vm_deallocate(mach_task_self(), (vm_address_t)oobuf, oolen);
- return KERN_FAILURE;
- }
-
- if (oolen > 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;
- }
-
- 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;
- }
-
- memcpy(out->databuf, ilbuf, illen);
- }
-
- *reply = kvbuf_decode(out);
- if (*reply == NULL)
- {
- /* DS returned no data */
- free(out->databuf);
- free(out);
- }
-
-#ifdef DEBUG
- asl_log(NULL, NULL, ASL_LEVEL_DEBUG, "_DSLookupQuery %d status OK", procno);
-#endif
- return status;
-}
-
-/*
- * Get an entry from a kvarray.
- * Calls the system information daemon if the list doesn't exist (first call),
- * or extracts the next entry if the list has been fetched.
- */
-__private_extern__ void *
-LI_getent(const char *procname, int *procnum, void *(*extract)(kvarray_t *), int tkey, size_t esize)
-{
- void *entry;
- struct li_thread_info *tdata;
- kvarray_t *reply;
- kern_return_t status;
-
- tdata = LI_data_create_key(tkey, esize);
- if (tdata == NULL) return NULL;
-
- if (tdata->li_vm == NULL)
- {
- if (*procnum < 0)
- {
- status = LI_DSLookupGetProcedureNumber(procname, procnum);
- if (status != KERN_SUCCESS)
- {
- LI_data_free_kvarray(tdata);
- tdata->li_vm = NULL;
- return NULL;
- }
- }
-
- reply = NULL;
- status = LI_DSLookupQuery(*procnum, NULL, &reply);
-
- if (status != KERN_SUCCESS)
- {
- LI_data_free_kvarray(tdata);
- tdata->li_vm = NULL;
- return NULL;
- }
-
- tdata->li_vm = (char *)reply;
- }
-
- entry = extract((kvarray_t *)(tdata->li_vm));
- if (entry == NULL)
- {
- LI_data_free_kvarray(tdata);
- tdata->li_vm = NULL;
- return NULL;
- }
-
- return entry;
-}
-
-__private_extern__ void *
-LI_getone(const char *procname, int *procnum, void *(*extract)(kvarray_t *), const char *key, const char *val)
-{
- void *entry;
- kvbuf_t *request;
- kvarray_t *reply;
- kern_return_t status;
-
- if (*procnum < 0)
- {
- status = LI_DSLookupGetProcedureNumber(procname, procnum);
- if (status != KERN_SUCCESS) return NULL;
- }
-
- request = kvbuf_query_key_val(key, val);
- if (request == NULL) return NULL;
-
- reply = NULL;
- status = LI_DSLookupQuery(*procnum, request, &reply);
- kvbuf_free(request);
-
- if (status != KERN_SUCCESS) return NULL;
-
- entry = extract(reply);
- kvarray_free(reply);
-
- return entry;
-}
-
-__private_extern__
-int LI_L1_cache_check(int tkey)
-{
- int check, x;
- const char *notify_key;
-
- /* check if L1 cache is disabled */
- if (gL1CacheEnabled == 0) return LI_L1_CACHE_DISABLED;
-
- /* Initialize on first call */
- if (_L1_notify_token[0] == -1)
- {
- pthread_mutex_lock(&_notify_lock);
- if (_L1_notify_token[0] == -1) notify_register_check(L1_CACHE_NOTIFICATION_KEY_GLOBAL, &(_L1_notify_token[0]));
- pthread_mutex_unlock(&_notify_lock);
- }
-
- if (_L1_notify_token[0] == -1) return LI_L1_CACHE_FAILED;
-
- check = 1;
- if (notify_check(_L1_notify_token[0], &check) != 0) return LI_L1_CACHE_FAILED;
- if (check == 1) return LI_L1_CACHE_STALE;
-
- x = 0;
- notify_key = NULL;
-
- switch (tkey)
- {
- case _li_data_key_group:
- {
- x = 1;
- notify_key = L1_CACHE_NOTIFICATION_KEY_GROUP;
- break;
- }
- case _li_data_key_host:
- {
- x = 2;
- notify_key = L1_CACHE_NOTIFICATION_KEY_HOST;
- break;
- }
- case _li_data_key_service:
- {
- x = 3;
- notify_key = L1_CACHE_NOTIFICATION_KEY_SERVICE;
- break;
- }
- case _li_data_key_user:
- {
- x = 4;
- notify_key = L1_CACHE_NOTIFICATION_KEY_USER;
- break;
- }
- default: break;
- }
-
- if ((x != 0) && (notify_key != NULL))
- {
- /* Initialize on first call */
- if (_L1_notify_token[x] == -1)
- {
- pthread_mutex_lock(&_notify_lock);
- if (_L1_notify_token[x] == -1) notify_register_check(notify_key, &(_L1_notify_token[x]));
- pthread_mutex_unlock(&_notify_lock);
- }
-
- if (_L1_notify_token[x] == -1) return LI_L1_CACHE_FAILED;
-
- check = 1;
- if (notify_check(_L1_notify_token[x], &check) != 0) return LI_L1_CACHE_FAILED;
- if (check == 1) return LI_L1_CACHE_STALE;
- }
-
- return LI_L1_CACHE_OK;
-}
-
-static uint32_t
-padsize(size_t curr, size_t item, const uint32_t *align)
-{
- uint32_t na, diff;
-
- if (item > 8) item = 8;
-
- na = align[item];
- if (na == 0) return 0;
-
- diff = curr % na;
- if (diff == 0) return 0;
-
- return na - diff;
-}
-
-
-/*
- * Create a structure using in-line memory (i.e. all one blob).
- * This reduces malloc/free workload.
- *
- * Structutre components may be strings, 1, 2, 4, or 8-byte values,
- * lists of strings, or lists of 4, 8, or 16-byte values.
- *
- * Format keys:
- * s NUL terminated string
- * 1 1 byte value
- * 2 2 byte value
- * 4 4 byte value
- * 8 8 byte value
- * L long (32 or 64 bits, depending on architecture)
- * * NULL-terminated list of strings
- * a NULL-terminated list of 4-byte values
- * b NULL-terminated list of 8-byte values
- * c NULL-terminated list of 16-byte values
- *
- */
-__private_extern__ void *
-LI_ils_create(char *fmt, ...)
-{
- va_list ap;
- char *arg, *f;
- char **list;
- void *hp, *dp, *lp, *ils;
- uint8_t u8;
- uint16_t u16;
- uint32_t u32, i, pad;
- uint64_t u64;
- unsigned long l;
- size_t memsize, hsize, csize, slen, largest;
- const uint32_t *align;
-
- if (fmt == NULL) return NULL;
-
- largest = 0;
- align = align_32;
- if (sizeof(char *) == 8) align = align_64;
-
- /* first pass: calculate size */
- memsize = ILS_MAGIC_SIZE;
- hsize = 0;
-
- va_start(ap, fmt);
-
- for (f = fmt; (*f) != '\0'; f++)
- {
- csize = 0;
- slen = 0;
-
- if (*f == 's')
- {
- if (largest < sizeof(char *)) largest = sizeof(char *);
-
- csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
- arg = va_arg(ap, char *);
- if (arg != NULL) slen = strlen(arg) + 1;
- }
- else if (*f == '1')
- {
- if (largest < 1) largest = 1;
-
- csize = 1;
- u8 = va_arg(ap, int);
- }
- else if (*f == '2')
- {
- if (largest < 2) largest = 2;
-
- csize = 2 + padsize(hsize, 2, align);
- u16 = va_arg(ap, int);
- }
- else if (*f == '4')
- {
- if (largest < 4) largest = 4;
-
- csize = 4 + padsize(hsize, 4, align);
- u32 = va_arg(ap, uint32_t);
- }
- else if (*f == '8')
- {
- if (largest < 8) largest = 8;
-
- csize = 8 + padsize(hsize, 8, align);
- u64 = va_arg(ap, uint64_t);
- }
- else if (*f == 'L')
- {
- if (largest < sizeof(unsigned long)) largest = sizeof(unsigned long);
-
- csize = sizeof(unsigned long) + padsize(hsize, sizeof(unsigned long), align);
- l = va_arg(ap, unsigned long);
- }
- else if (*f == '*')
- {
- /* NULL-terminated list of strings */
- if (largest < sizeof(char *)) largest = sizeof(char *);
-
- csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
- list = va_arg(ap, char **);
- if (list != NULL)
- {
- for (i = 0; list[i] != NULL; i++)
- {
- slen += sizeof(char *);
- slen += (strlen(list[i]) + 1);
- }
-
- slen += sizeof(char *);
- }
- }
- else if (*f == 'a')
- {
- /* NULL-terminated list of 4-byte values */
- if (largest < sizeof(char *)) largest = sizeof(char *);
-
- csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
- list = va_arg(ap, char **);
- if (list != NULL)
- {
- for (i = 0; list[i] != NULL; i++)
- {
- slen += sizeof(char *);
- slen += 4;
- }
-
- slen += sizeof(char *);
- }
- }
- else if (*f == 'b')
- {
- /* NULL-terminated list of 8-byte values */
- if (largest < sizeof(char *)) largest = sizeof(char *);
-
- csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
- list = va_arg(ap, char **);
- if (list != NULL)
- {
- for (i = 0; list[i] != NULL; i++)
- {
- slen += sizeof(char *);
- slen += 8;
- }
-
- slen += sizeof(char *);
- }
- }
- else if (*f == 'c')
- {
- /* NULL-terminated list of 16-byte values */
- if (largest < sizeof(char *)) largest = sizeof(char *);
-
- csize = sizeof(char *) + padsize(hsize, sizeof(char *), align);
- list = va_arg(ap, char **);
- if (list != NULL)
- {
- for (i = 0; list[i] != NULL; i++)
- {
- slen += sizeof(char *);
- slen += 16;
- }
-
- slen += sizeof(char *);
- }
- }
- else return NULL;
-
- memsize += csize;
- memsize += slen;
- hsize += csize;
- }
-
- va_end(ap);
-
- pad = padsize(hsize, largest, align);
- memsize += pad;
- hsize += pad;
-
- ils = malloc(memsize);
- if (ils == NULL)
- {
- errno = ENOMEM;
- return NULL;
- }
-
- /* insert magic cookie */
- dp = ils + hsize;
- memcpy(dp, ILS_MAGIC, ILS_MAGIC_SIZE);
- dp += ILS_MAGIC_SIZE;
-
- hp = ils;
- hsize = 0;
-
- /* second pass: copy data */
- va_start(ap, fmt);
- for (f = fmt; (*f) != '\0'; f++)
- {
- if (*f == 's')
- {
- pad = padsize(hsize, sizeof(char *), align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- arg = va_arg(ap, char *);
- if (arg == NULL)
- {
- memset(hp, 0, sizeof(char *));
- }
- else
- {
- memcpy(hp, &dp, sizeof(char *));
- slen = strlen(arg) + 1;
- memcpy(dp, arg, slen);
- dp += slen;
- }
-
- hp += sizeof(char *);
- hsize += sizeof(char *);
- }
- else if (*f == '1')
- {
- u8 = va_arg(ap, int);
- memcpy(hp, &u8, sizeof(uint8_t));
- hp += sizeof(uint8_t);
- }
- else if (*f == '2')
- {
- pad = padsize(hsize, 2, align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- u16 = va_arg(ap, int);
- memcpy(hp, &u16, sizeof(uint16_t));
-
- hp += sizeof(uint16_t);
- hsize += sizeof(uint16_t);
- }
- else if (*f == '4')
- {
- pad = padsize(hsize, 4, align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- u32 = va_arg(ap, uint32_t);
- memcpy(hp, &u32, sizeof(uint32_t));
-
- hp += sizeof(uint32_t);
- hsize += sizeof(uint32_t);
- }
- else if (*f == '8')
- {
- pad = padsize(hsize, 8, align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- u64 = va_arg(ap, uint64_t);
- memcpy(hp, &u64, sizeof(uint64_t));
-
- hp += sizeof(uint64_t);
- hsize += sizeof(uint64_t);
- }
- else if (*f == 'L')
- {
- pad = padsize(hsize, sizeof(unsigned long), align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- l = va_arg(ap, unsigned long);
- memcpy(hp, &l, sizeof(unsigned long));
-
- hp += sizeof(unsigned long);
- hsize += sizeof(unsigned long);
- }
- else if (*f == '*')
- {
- pad = padsize(hsize, sizeof(char *), align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- list = va_arg(ap, char **);
-
- if (list == NULL)
- {
- memset(hp, 0, sizeof(char *));
- }
- else
- {
- memcpy(hp, &dp, sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++);
-
- lp = dp;
- dp += ((i + 1) * sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++)
- {
- memcpy(lp, &dp, sizeof(char *));
- lp += sizeof(char *);
- slen = strlen(list[i]) + 1;
- memcpy(dp, list[i], slen);
- dp += slen;
- }
-
- memset(lp, 0, sizeof(char *));
- }
-
- hp += sizeof(char *);
- hsize += sizeof(char *);
- }
- else if (*f == 'a')
- {
- pad = padsize(hsize, sizeof(char *), align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- list = va_arg(ap, char **);
-
- if (list == NULL)
- {
- memset(hp, 0, sizeof(char *));
- }
- else
- {
- memcpy(hp, &dp, sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++);
-
- lp = dp;
- dp += ((i + 1) * sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++)
- {
- memcpy(lp, &dp, sizeof(char *));
- lp += sizeof(char *);
- slen = 4;
- memcpy(dp, list[i], slen);
- dp += slen;
- }
-
- memset(lp, 0, sizeof(char *));
- }
-
- hp += sizeof(char *);
- hsize += sizeof(char *);
- }
- else if (*f == 'b')
- {
- pad = padsize(hsize, sizeof(char *), align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- list = va_arg(ap, char **);
-
- if (list == NULL)
- {
- memset(hp, 0, sizeof(char *));
- }
- else
- {
- memcpy(hp, &dp, sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++);
-
- lp = dp;
- dp += ((i + 1) * sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++)
- {
- memcpy(lp, &dp, sizeof(char *));
- lp += sizeof(char *);
- slen = 8;
- memcpy(dp, list[i], slen);
- dp += slen;
- }
-
- memset(lp, 0, sizeof(char *));
- }
-
- hp += sizeof(char *);
- hsize += sizeof(char *);
- }
- else if (*f == 'c')
- {
- pad = padsize(hsize, sizeof(char *), align);
- if (pad != 0)
- {
- memset(hp, 0, pad);
- hp += pad;
- hsize += pad;
- }
-
- list = va_arg(ap, char **);
-
- if (list == NULL)
- {
- memset(hp, 0, sizeof(char *));
- }
- else
- {
- memcpy(hp, &dp, sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++);
-
- lp = dp;
- dp += ((i + 1) * sizeof(char *));
-
- for (i = 0; list[i] != NULL; i++)
- {
- memcpy(lp, &dp, sizeof(char *));
- lp += sizeof(char *);
- slen = 16;
- memcpy(dp, list[i], slen);
- dp += slen;
- }
-
- memset(lp, 0, sizeof(char *));
- }
-
- hp += sizeof(char *);
- hsize += sizeof(char *);
- }
- }
-
- va_end(ap);
-
- pad = padsize(hsize, largest, align);
- if (pad > 0) memset(hp, 0, pad);
-
- return ils;
-}
-
-__private_extern__ int
-LI_ils_free(void *ils, size_t len)
-{
- char *p;
-
- if (ils == NULL) return 0;
-
- p = ils + len;
- if (memcmp(p, ILS_MAGIC, ILS_MAGIC_SIZE) != 0) return -1;
-
- free(ils);
-
- return 0;
-}
-
-kern_return_t
-_lookup_link(mach_port_t server, char *name, int *procno)
-{
- syslog(LOG_ERR, "RED ALERT! lookupd call %s from pid %u", name, getpid());
- return KERN_FAILURE;
-}
-
-kern_return_t
-_lookup_one(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char *outdata, mach_msg_type_number_t *outdataCnt)
-{
- return KERN_FAILURE;
-}
-
-kern_return_t
-_lookup_all(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt)
-{
- return KERN_FAILURE;
-}
-
-kern_return_t
-_lookup_ooall(mach_port_t server, int proc, char *indata, mach_msg_type_number_t indataCnt, char **outdata, mach_msg_type_number_t *outdataCnt)
-{
- return KERN_FAILURE;
-}