summaryrefslogtreecommitdiff
path: root/data/libresolv/dnsinfo_copy.c
diff options
context:
space:
mode:
Diffstat (limited to 'data/libresolv/dnsinfo_copy.c')
-rw-r--r--data/libresolv/dnsinfo_copy.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/data/libresolv/dnsinfo_copy.c b/data/libresolv/dnsinfo_copy.c
new file mode 100644
index 000000000..882b697b9
--- /dev/null
+++ b/data/libresolv/dnsinfo_copy.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * 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 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ 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, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+/*
+ * Modification History
+ *
+ * March 9, 2004 Allan Nathanson <ajn@apple.com>
+ * - initial revision
+ */
+
+#include <stdlib.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "dnsinfo.h"
+#include "dnsinfo_private.h"
+#include "shared_dns_info.h"
+
+
+static boolean_t
+add_list(void **padding, uint32_t *n_padding, int32_t count, int32_t size, void **list)
+{
+ int32_t need;
+
+ need = count * size;
+ if (need > *n_padding) {
+ return FALSE;
+ }
+
+ *list = (need == 0) ? NULL : *padding;
+ *padding += need;
+ *n_padding -= need;
+ return TRUE;
+}
+
+
+static _dns_config_buf_t *
+copy_dns_info()
+{
+ uint8_t *buf = NULL;
+ dnsDataOut_t dataRef = NULL;
+ mach_msg_type_number_t dataLen = 0;
+ mach_port_t server;
+ kern_return_t status;
+
+ server = _dns_configuration_server_port();
+ if (server == MACH_PORT_NULL) {
+ return NULL;
+ }
+
+ status = shared_dns_infoGet(server, &dataRef, &dataLen);
+ (void)mach_port_deallocate(mach_task_self(), server);
+ if (status != KERN_SUCCESS) {
+ mach_error("shared_dns_infoGet():", status);
+ return NULL;
+ }
+
+ if (dataRef != NULL) {
+ if (dataLen >= sizeof(_dns_config_buf_t)) {
+ _dns_config_buf_t *config = (_dns_config_buf_t *)dataRef;
+ uint32_t len;
+ uint32_t n_padding = ntohl(config->n_padding);
+
+ len = dataLen + n_padding;
+ buf = malloc(len);
+ bcopy((void *)dataRef, buf, dataLen);
+ bzero(&buf[dataLen], n_padding);
+ }
+
+ status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
+ if (status != KERN_SUCCESS) {
+ mach_error("vm_deallocate():", status);
+ free(buf);
+ return NULL;
+ }
+ }
+
+ return (_dns_config_buf_t *)buf;
+}
+
+
+static dns_resolver_t *
+expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32_t *n_padding)
+{
+ dns_attribute_t *attribute;
+ uint32_t n_attribute;
+ int32_t n_nameserver = 0;
+ int32_t n_search = 0;
+ int32_t n_sortaddr = 0;
+ dns_resolver_t *resolver = (dns_resolver_t *)&buf->resolver;
+
+ if (n_buf < sizeof(_dns_resolver_buf_t)) {
+ goto error;
+ }
+
+ // initialize domain
+
+ resolver->domain = NULL;
+
+ // initialize nameserver list
+
+ resolver->n_nameserver = ntohl(resolver->n_nameserver);
+ if (!add_list(padding,
+ n_padding,
+ resolver->n_nameserver,
+ sizeof(struct sockaddr *),
+ (void **)&resolver->nameserver)) {
+ goto error;
+ }
+
+ // initialize port
+
+ resolver->port = ntohs(resolver->port);
+
+ // initialize search list
+
+ resolver->n_search = ntohl(resolver->n_search);
+ if (!add_list(padding,
+ n_padding,
+ resolver->n_search,
+ sizeof(char *),
+ (void **)&resolver->search)) {
+ goto error;
+ }
+
+ // initialize sortaddr list
+
+ resolver->n_sortaddr = ntohl(resolver->n_sortaddr);
+ if (!add_list(padding,
+ n_padding,
+ resolver->n_sortaddr,
+ sizeof(dns_sortaddr_t *),
+ (void **)&resolver->sortaddr)) {
+ goto error;
+ }
+
+ // initialize options
+
+ resolver->options = NULL;
+
+ // initialize timeout
+
+ resolver->timeout = ntohl(resolver->timeout);
+
+ // initialize search_order
+
+ resolver->search_order = ntohl(resolver->search_order);
+
+ // process resolver buffer "attribute" data
+
+ n_attribute = n_buf - sizeof(_dns_resolver_buf_t);
+ attribute = (dns_attribute_t *)&buf->attribute[0];
+ if (n_attribute != ntohl(buf->n_attribute)) {
+ goto error;
+ }
+
+ while (n_attribute >= sizeof(dns_attribute_t)) {
+ int32_t attribute_length = ntohl(attribute->length);
+
+ switch (ntohl(attribute->type)) {
+ case RESOLVER_ATTRIBUTE_DOMAIN :
+ resolver->domain = (char *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_ADDRESS :
+ resolver->nameserver[n_nameserver++] = (struct sockaddr *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_SEARCH :
+ resolver->search[n_search++] = (char *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_SORTADDR :
+ resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)&attribute->attribute[0];
+ break;
+
+ case RESOLVER_ATTRIBUTE_OPTIONS :
+ resolver->options = (char *)&attribute->attribute[0];
+ break;
+
+ default :
+ break;
+ }
+
+ attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
+ n_attribute -= attribute_length;
+ }
+
+ if ((n_nameserver != resolver->n_nameserver) ||
+ (n_search != resolver->n_search ) ||
+ (n_sortaddr != resolver->n_sortaddr )) {
+ goto error;
+ }
+
+ return resolver;
+
+ error :
+
+ return NULL;
+}
+
+
+static dns_config_t *
+expand_config(_dns_config_buf_t *buf)
+{
+ dns_attribute_t *attribute;
+ dns_config_t *config = (dns_config_t *)buf;
+ uint32_t n_attribute;
+ uint32_t n_padding;
+ int32_t n_resolver = 0;
+ void *padding;
+
+ // establish padding
+
+ padding = &buf->attribute[ntohl(buf->n_attribute)];
+ n_padding = ntohl(buf->n_padding);
+
+ // initialize resolver list
+
+ config->n_resolver = ntohl(config->n_resolver);
+ if (!add_list(&padding,
+ &n_padding,
+ config->n_resolver,
+ sizeof(dns_resolver_t *),
+ (void **)&config->resolver)) {
+ goto error;
+ }
+
+ // process configuration buffer "attribute" data
+
+ n_attribute = ntohl(buf->n_attribute);
+ attribute = (dns_attribute_t *)&buf->attribute[0];
+
+ while (n_attribute >= sizeof(dns_attribute_t)) {
+ int32_t attribute_length = ntohl(attribute->length);
+
+ switch (ntohl(attribute->type)) {
+ case CONFIG_ATTRIBUTE_RESOLVER : {
+ dns_resolver_t *resolver;
+
+ // expand resolver buffer
+
+ resolver = expand_resolver((_dns_resolver_buf_t *)&attribute->attribute[0],
+ attribute_length - sizeof(dns_attribute_t),
+ &padding,
+ &n_padding);
+ if (resolver == NULL) {
+ goto error;
+ }
+
+ // add resolver to config list
+
+ config->resolver[n_resolver++] = resolver;
+
+ break;
+ }
+
+ default :
+ break;
+ }
+
+ attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
+ n_attribute -= attribute_length;
+ }
+
+ if (n_resolver != config->n_resolver) {
+ goto error;
+ }
+
+ return config;
+
+ error :
+
+ return NULL;
+}
+
+
+__private_extern__
+const char *
+dns_configuration_notify_key()
+{
+ return _dns_configuration_notify_key();
+}
+
+
+__private_extern__
+dns_config_t *
+dns_configuration_copy()
+{
+ _dns_config_buf_t *buf;
+ dns_config_t *config;
+
+ buf = copy_dns_info();
+ if (buf == NULL) {
+ return NULL;
+ }
+
+ config = expand_config(buf);
+ if (config == NULL) {
+ free(buf);
+ return NULL;
+ }
+
+ return config;
+}
+
+
+__private_extern__
+void
+dns_configuration_free(dns_config_t *config)
+{
+ if (config == NULL) {
+ return;
+ }
+
+ free((void *)config);
+ return;
+}