2 * Copyright (c) 2004, 2006, 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include <mach/mach.h>
27 #include <mach/mach_error.h>
29 #include "dnsinfo_create.h"
30 #include "dnsinfo_private.h"
31 #include "shared_dns_info.h"
34 #define ROUNDUP(a, size) \
35 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
39 * to avoid extra calls to realloc() we want to pre-allocate the initial
40 * resolver and configuration buffers of a sufficient size that they would
41 * not normally need to be expanded.
43 #define INITIAL_CONFIGURATION_BUF_SIZE 8192
44 #define INITIAL_RESOLVER_BUF_SIZE 1024
48 * DNS [configuration] buffer functions
53 _dns_configuration_create()
55 _dns_config_buf_t
*config
;
57 config
= calloc(1, INITIAL_CONFIGURATION_BUF_SIZE
);
58 // config->n_attribute = 0;
59 // config->n_padding = 0;
60 return (dns_create_config_t
)config
;
65 config_add_attribute(dns_create_config_t
*_config
,
66 uint32_t attribute_type
,
67 uint32_t attribute_length
,
69 uint32_t extra_padding
)
71 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
72 dns_attribute_t
*header
;
77 uint32_t rounded_length
;
81 oldLen
= ntohl(config
->n_attribute
);
82 rounded_length
= ROUNDUP(attribute_length
, sizeof(uint32_t));
83 newLen
= sizeof(dns_attribute_t
) + rounded_length
;
84 newSize
= sizeof(_dns_config_buf_t
) + oldLen
+ newLen
;
85 if (newSize
> INITIAL_CONFIGURATION_BUF_SIZE
) {
86 config
= realloc(config
, newSize
);
88 config
->n_attribute
= htonl(ntohl(config
->n_attribute
) + newLen
);
90 // increment additional padding that will be needed (later)
91 config
->n_padding
= htonl(ntohl(config
->n_padding
) + extra_padding
);
93 // add attribute [header]
95 header
= (dns_attribute_t
*)&config
->attribute
[oldLen
];
96 header
->type
= htonl(attribute_type
);
97 header
->length
= htonl(newLen
);
99 // add attribute [data]
101 bcopy(attribute
, &header
->attribute
[0], attribute_length
);
102 for (i
= attribute_length
; i
< rounded_length
; i
++) {
103 header
->attribute
[i
] = 0;
106 *_config
= (dns_create_config_t
)config
;
112 _dns_configuration_add_resolver(dns_create_config_t
*_config
,
113 dns_create_resolver_t _resolver
)
115 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
116 uint32_t padding
= 0;
117 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)_resolver
;
120 * compute the amount of space that will be needed for
121 * pointers to the resolver, the nameservers, the search
122 * list, and the sortaddr list.
124 padding
+= sizeof(DNS_PTR(dns_resolver_t
*, x
));
125 if (resolver
->resolver
.n_nameserver
!= 0) {
126 padding
+= ntohl(resolver
->resolver
.n_nameserver
) * sizeof(DNS_PTR(struct sockaddr
*, x
));
128 if (resolver
->resolver
.n_search
!= 0) {
129 padding
+= ntohl(resolver
->resolver
.n_search
) * sizeof(DNS_PTR(char *, x
));
131 if (resolver
->resolver
.n_sortaddr
!= 0) {
132 padding
+= ntohl(resolver
->resolver
.n_sortaddr
) * sizeof(DNS_PTR(dns_sortaddr_t
*, x
));
135 if ((ntohl(resolver
->resolver
.flags
) & DNS_RESOLVER_FLAGS_SCOPED
) == 0) {
136 config
->config
.n_resolver
= htonl(ntohl(config
->config
.n_resolver
) + 1);
137 config_add_attribute(_config
,
138 CONFIG_ATTRIBUTE_RESOLVER
,
139 sizeof(_dns_resolver_buf_t
) + ntohl(resolver
->n_attribute
),
143 config
->config
.n_scoped_resolver
= htonl(ntohl(config
->config
.n_scoped_resolver
) + 1);
144 config_add_attribute(_config
,
145 CONFIG_ATTRIBUTE_SCOPED_RESOLVER
,
146 sizeof(_dns_resolver_buf_t
) + ntohl(resolver
->n_attribute
),
156 _dns_configuration_store(dns_create_config_t
*_config
)
158 dnsDataOut_t dataRef
= NULL
;
159 mach_msg_type_number_t dataLen
= 0;
161 kern_return_t status
;
163 server
= _dns_configuration_server_port();
164 if (server
== MACH_PORT_NULL
) {
168 if (_config
!= NULL
) {
169 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
171 if (config
!= NULL
) {
172 dataRef
= (dnsDataOut_t
)config
;
173 dataLen
= sizeof(_dns_config_buf_t
) + ntohl(config
->n_attribute
);
177 status
= shared_dns_infoSet(server
, dataRef
, dataLen
);
178 (void) mach_port_deallocate(mach_task_self(), server
);
179 if (status
!= KERN_SUCCESS
) {
180 mach_error("shared_dns_infoSet():", status
);
189 _dns_configuration_free(dns_create_config_t
*_config
)
191 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
200 * DNS resolver configuration functions
203 dns_create_resolver_t
204 _dns_resolver_create()
206 _dns_resolver_buf_t
*buf
;
208 buf
= calloc(1, INITIAL_RESOLVER_BUF_SIZE
);
209 // buf->n_attribute = 0;
210 return (dns_create_resolver_t
)buf
;
215 _dns_resolver_add_attribute(dns_create_resolver_t
*_resolver
,
216 uint32_t attribute_type
,
217 uint32_t attribute_length
,
220 dns_attribute_t
*header
;
225 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
226 uint32_t rounded_length
;
230 oldLen
= ntohl(resolver
->n_attribute
);
231 rounded_length
= ROUNDUP(attribute_length
, sizeof(uint32_t));
232 newLen
= sizeof(dns_attribute_t
) + rounded_length
;
233 newSize
= sizeof(_dns_resolver_buf_t
) + oldLen
+ newLen
;
234 if (newSize
> INITIAL_RESOLVER_BUF_SIZE
) {
235 resolver
= realloc(resolver
, newSize
);
237 resolver
->n_attribute
= htonl(ntohl(resolver
->n_attribute
) + newLen
);
239 // add attribute [header]
241 header
= (dns_attribute_t
*)&resolver
->attribute
[oldLen
];
242 header
->type
= htonl(attribute_type
);
243 header
->length
= htonl(newLen
);
245 // add attribute [data]
247 bcopy(attribute
, &header
->attribute
[0], attribute_length
);
248 for (i
= attribute_length
; i
< rounded_length
; i
++) {
249 header
->attribute
[i
] = 0;
252 *_resolver
= (dns_create_resolver_t
)resolver
;
258 _dns_resolver_add_nameserver(dns_create_resolver_t
*_resolver
, struct sockaddr
*nameserver
)
260 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
262 resolver
->resolver
.n_nameserver
= htonl(ntohl(resolver
->resolver
.n_nameserver
) + 1);
263 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_ADDRESS
, nameserver
->sa_len
, (void *)nameserver
);
269 _dns_resolver_add_search(dns_create_resolver_t
*_resolver
, const char *search
)
271 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
273 resolver
->resolver
.n_search
= htonl(ntohl(resolver
->resolver
.n_search
) + 1);
274 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_SEARCH
, strlen(search
) + 1, (void *)search
);
280 _dns_resolver_set_domain(dns_create_resolver_t
*_resolver
, const char *domain
)
282 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_DOMAIN
, strlen(domain
) + 1, (void *)domain
);
288 _dns_resolver_set_flags(dns_create_resolver_t
*_resolver
, uint32_t flags
)
290 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
292 resolver
->resolver
.flags
= htonl(flags
);
298 _dns_resolver_set_if_index(dns_create_resolver_t
*_resolver
, uint32_t if_index
)
300 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
302 resolver
->resolver
.if_index
= htonl(if_index
);
308 _dns_resolver_set_options(dns_create_resolver_t
*_resolver
, const char *options
)
310 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_OPTIONS
, strlen(options
) + 1, (void *)options
);
316 _dns_resolver_set_order(dns_create_resolver_t
*_resolver
, uint32_t order
)
318 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
320 resolver
->resolver
.search_order
= htonl(order
);
326 _dns_resolver_set_port(dns_create_resolver_t
*_resolver
, uint16_t port
)
328 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
330 resolver
->resolver
.port
= htons(port
);
336 _dns_resolver_add_sortaddr(dns_create_resolver_t
*_resolver
, dns_sortaddr_t
*sortaddr
)
338 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
340 resolver
->resolver
.n_sortaddr
= htonl(ntohl(resolver
->resolver
.n_sortaddr
) + 1);
341 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_SORTADDR
, sizeof(dns_sortaddr_t
), (void *)sortaddr
);
347 _dns_resolver_set_timeout(dns_create_resolver_t
*_resolver
, uint32_t timeout
)
349 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
351 resolver
->resolver
.timeout
= htonl(timeout
);
357 _dns_resolver_free(dns_create_resolver_t
*_resolver
)
359 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;