2 * Copyright (c) 2004, 2006, 2009, 2011 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>
28 #include <CommonCrypto/CommonDigest.h>
30 #include "dnsinfo_create.h"
31 #include "dnsinfo_private.h"
32 #include "shared_dns_info.h"
33 #include "network_information_priv.h"
36 #define ROUNDUP(a, size) \
37 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
41 * to avoid extra calls to realloc() we want to pre-allocate the initial
42 * resolver and configuration buffers of a sufficient size that they would
43 * not normally need to be expanded.
45 #define INITIAL_CONFIGURATION_BUF_SIZE 8192
46 #define INITIAL_RESOLVER_BUF_SIZE 1024
50 * DNS [configuration] buffer functions
55 _dns_configuration_create()
57 _dns_config_buf_t
*config
;
59 config
= calloc(1, INITIAL_CONFIGURATION_BUF_SIZE
);
60 // config->n_attribute = 0;
61 // config->n_padding = 0;
62 return (dns_create_config_t
)config
;
67 config_add_attribute(dns_create_config_t
*_config
,
68 uint32_t attribute_type
,
69 uint32_t attribute_length
,
71 uint32_t extra_padding
)
73 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
74 dns_attribute_t
*header
;
79 uint32_t rounded_length
;
83 oldLen
= ntohl(config
->n_attribute
);
84 rounded_length
= ROUNDUP(attribute_length
, sizeof(uint32_t));
85 newLen
= sizeof(dns_attribute_t
) + rounded_length
;
86 newSize
= sizeof(_dns_config_buf_t
) + oldLen
+ newLen
;
87 if (newSize
> INITIAL_CONFIGURATION_BUF_SIZE
) {
88 config
= realloc(config
, newSize
);
90 config
->n_attribute
= htonl(ntohl(config
->n_attribute
) + newLen
);
92 // increment additional padding that will be needed (later)
93 config
->n_padding
= htonl(ntohl(config
->n_padding
) + extra_padding
);
95 // add attribute [header]
97 /* ALIGN: _dns_config_buf_t is int aligned */
98 header
= (dns_attribute_t
*)(void *)&config
->attribute
[oldLen
];
99 header
->type
= htonl(attribute_type
);
100 header
->length
= htonl(newLen
);
102 // add attribute [data]
104 bcopy(attribute
, &header
->attribute
[0], attribute_length
);
105 for (i
= attribute_length
; i
< rounded_length
; i
++) {
106 header
->attribute
[i
] = 0;
109 *_config
= (dns_create_config_t
)config
;
115 _dns_configuration_add_resolver(dns_create_config_t
*_config
,
116 dns_create_resolver_t _resolver
)
118 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
119 uint32_t padding
= 0;
120 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)_resolver
;
123 * compute the amount of space that will be needed for
124 * pointers to the resolver, the nameservers, the search
125 * list, and the sortaddr list.
127 padding
+= sizeof(DNS_PTR(dns_resolver_t
*, x
));
128 if (resolver
->resolver
.n_nameserver
!= 0) {
129 padding
+= ntohl(resolver
->resolver
.n_nameserver
) * sizeof(DNS_PTR(struct sockaddr
*, x
));
131 if (resolver
->resolver
.n_search
!= 0) {
132 padding
+= ntohl(resolver
->resolver
.n_search
) * sizeof(DNS_PTR(char *, x
));
134 if (resolver
->resolver
.n_sortaddr
!= 0) {
135 padding
+= ntohl(resolver
->resolver
.n_sortaddr
) * sizeof(DNS_PTR(dns_sortaddr_t
*, x
));
138 if ((ntohl(resolver
->resolver
.flags
) & DNS_RESOLVER_FLAGS_SCOPED
) == 0) {
139 config
->config
.n_resolver
= htonl(ntohl(config
->config
.n_resolver
) + 1);
140 config_add_attribute(_config
,
141 CONFIG_ATTRIBUTE_RESOLVER
,
142 sizeof(_dns_resolver_buf_t
) + ntohl(resolver
->n_attribute
),
146 config
->config
.n_scoped_resolver
= htonl(ntohl(config
->config
.n_scoped_resolver
) + 1);
147 config_add_attribute(_config
,
148 CONFIG_ATTRIBUTE_SCOPED_RESOLVER
,
149 sizeof(_dns_resolver_buf_t
) + ntohl(resolver
->n_attribute
),
158 _nwi_state_store(nwi_state
* state
)
161 kern_return_t status
;
162 dnsDataOut_t dataRef
= (dnsDataOut_t
) state
;
163 mach_msg_type_number_t dataLen
= state
->size
;
165 server
= _dns_configuration_server_port();
166 if (server
== MACH_PORT_NULL
) {
170 status
= shared_nwi_stateSet(server
, dataRef
, dataLen
);
172 (void) mach_port_deallocate(mach_task_self(), server
);
174 if (status
!= KERN_SUCCESS
) {
183 _dns_configuration_signature(dns_create_config_t
*_config
,
184 unsigned char *signature
,
185 size_t signature_len
)
187 bzero(signature
, signature_len
);
189 if (_config
!= NULL
) {
190 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
192 if (config
!= NULL
) {
195 unsigned char sha1_buf
[CC_SHA1_DIGEST_LENGTH
];
197 sha1
= (signature_len
>= CC_SHA1_DIGEST_LENGTH
) ? signature
: sha1_buf
;
201 sizeof(_dns_config_buf_t
) + ntohl(config
->n_attribute
));
202 CC_SHA1_Final(sha1
, &ctx
);
203 if (sha1
!= signature
) {
204 bcopy(sha1
, signature
, signature_len
);
214 _dns_configuration_store(dns_create_config_t
*_config
)
216 dnsDataOut_t dataRef
= NULL
;
217 mach_msg_type_number_t dataLen
= 0;
219 kern_return_t status
;
221 server
= _dns_configuration_server_port();
222 if (server
== MACH_PORT_NULL
) {
226 if (_config
!= NULL
) {
227 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
229 if (config
!= NULL
) {
230 dataRef
= (dnsDataOut_t
)config
;
231 dataLen
= sizeof(_dns_config_buf_t
) + ntohl(config
->n_attribute
);
235 status
= shared_dns_infoSet(server
, dataRef
, dataLen
);
236 (void) mach_port_deallocate(mach_task_self(), server
);
237 if (status
!= KERN_SUCCESS
) {
238 mach_error("shared_dns_infoSet():", status
);
247 _dns_configuration_free(dns_create_config_t
*_config
)
249 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
258 * DNS resolver configuration functions
261 dns_create_resolver_t
262 _dns_resolver_create()
264 _dns_resolver_buf_t
*buf
;
266 buf
= calloc(1, INITIAL_RESOLVER_BUF_SIZE
);
267 // buf->n_attribute = 0;
268 return (dns_create_resolver_t
)buf
;
273 _dns_resolver_add_attribute(dns_create_resolver_t
*_resolver
,
274 uint32_t attribute_type
,
275 uint32_t attribute_length
,
278 dns_attribute_t
*header
;
283 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
284 uint32_t rounded_length
;
288 oldLen
= ntohl(resolver
->n_attribute
);
289 rounded_length
= ROUNDUP(attribute_length
, sizeof(uint32_t));
290 newLen
= sizeof(dns_attribute_t
) + rounded_length
;
291 newSize
= sizeof(_dns_resolver_buf_t
) + oldLen
+ newLen
;
292 if (newSize
> INITIAL_RESOLVER_BUF_SIZE
) {
293 resolver
= realloc(resolver
, newSize
);
295 resolver
->n_attribute
= htonl(ntohl(resolver
->n_attribute
) + newLen
);
297 // add attribute [header]
299 /* ALIGN: _dns_config_buf_t is int aligned */
300 header
= (dns_attribute_t
*)(void *)&resolver
->attribute
[oldLen
];
301 header
->type
= htonl(attribute_type
);
302 header
->length
= htonl(newLen
);
304 // add attribute [data]
306 bcopy(attribute
, &header
->attribute
[0], attribute_length
);
307 for (i
= attribute_length
; i
< rounded_length
; i
++) {
308 header
->attribute
[i
] = 0;
311 *_resolver
= (dns_create_resolver_t
)resolver
;
317 _dns_resolver_add_nameserver(dns_create_resolver_t
*_resolver
, struct sockaddr
*nameserver
)
319 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
321 resolver
->resolver
.n_nameserver
= htonl(ntohl(resolver
->resolver
.n_nameserver
) + 1);
322 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_ADDRESS
, nameserver
->sa_len
, (void *)nameserver
);
328 _dns_resolver_add_search(dns_create_resolver_t
*_resolver
, const char *search
)
330 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
332 resolver
->resolver
.n_search
= htonl(ntohl(resolver
->resolver
.n_search
) + 1);
333 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_SEARCH
, strlen(search
) + 1, (void *)search
);
339 _dns_resolver_add_sortaddr(dns_create_resolver_t
*_resolver
, dns_sortaddr_t
*sortaddr
)
341 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
343 resolver
->resolver
.n_sortaddr
= htonl(ntohl(resolver
->resolver
.n_sortaddr
) + 1);
344 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_SORTADDR
, sizeof(dns_sortaddr_t
), (void *)sortaddr
);
350 _dns_resolver_set_domain(dns_create_resolver_t
*_resolver
, const char *domain
)
352 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_DOMAIN
, strlen(domain
) + 1, (void *)domain
);
358 _dns_resolver_set_flags(dns_create_resolver_t
*_resolver
, uint32_t flags
)
360 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
362 resolver
->resolver
.flags
= htonl(flags
);
368 _dns_resolver_set_if_index(dns_create_resolver_t
*_resolver
, uint32_t if_index
)
370 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
372 resolver
->resolver
.if_index
= htonl(if_index
);
378 _dns_resolver_set_options(dns_create_resolver_t
*_resolver
, const char *options
)
380 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_OPTIONS
, strlen(options
) + 1, (void *)options
);
386 _dns_resolver_set_order(dns_create_resolver_t
*_resolver
, uint32_t order
)
388 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
390 resolver
->resolver
.search_order
= htonl(order
);
396 _dns_resolver_set_port(dns_create_resolver_t
*_resolver
, uint16_t port
)
398 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
400 resolver
->resolver
.port
= htons(port
);
406 _dns_resolver_set_reach_flags(dns_create_resolver_t
*_resolver
, uint32_t reach_flags
)
408 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
410 resolver
->resolver
.reach_flags
= htonl(reach_flags
);
416 _dns_resolver_set_timeout(dns_create_resolver_t
*_resolver
, uint32_t timeout
)
418 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
420 resolver
->resolver
.timeout
= htonl(timeout
);
426 _dns_resolver_free(dns_create_resolver_t
*_resolver
)
428 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;