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 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
),
148 _dns_configuration_store(dns_create_config_t
*_config
)
150 dnsDataOut_t dataRef
= NULL
;
151 mach_msg_type_number_t dataLen
= 0;
153 kern_return_t status
;
155 server
= _dns_configuration_server_port();
156 if (server
== MACH_PORT_NULL
) {
160 if (_config
!= NULL
) {
161 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
163 if (config
!= NULL
) {
164 dataRef
= (dnsDataOut_t
)config
;
165 dataLen
= sizeof(_dns_config_buf_t
) + ntohl(config
->n_attribute
);
169 status
= shared_dns_infoSet(server
, dataRef
, dataLen
);
170 (void) mach_port_deallocate(mach_task_self(), server
);
171 if (status
!= KERN_SUCCESS
) {
172 mach_error("shared_dns_infoSet():", status
);
181 _dns_configuration_free(dns_create_config_t
*_config
)
183 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)*_config
;
192 * DNS resolver configuration functions
195 dns_create_resolver_t
196 _dns_resolver_create()
198 _dns_resolver_buf_t
*buf
;
200 buf
= calloc(1, INITIAL_RESOLVER_BUF_SIZE
);
201 // buf->n_attribute = 0;
202 return (dns_create_resolver_t
)buf
;
207 _dns_resolver_add_attribute(dns_create_resolver_t
*_resolver
,
208 uint32_t attribute_type
,
209 uint32_t attribute_length
,
212 dns_attribute_t
*header
;
217 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
218 uint32_t rounded_length
;
222 oldLen
= ntohl(resolver
->n_attribute
);
223 rounded_length
= ROUNDUP(attribute_length
, sizeof(uint32_t));
224 newLen
= sizeof(dns_attribute_t
) + rounded_length
;
225 newSize
= sizeof(_dns_resolver_buf_t
) + oldLen
+ newLen
;
226 if (newSize
> INITIAL_RESOLVER_BUF_SIZE
) {
227 resolver
= realloc(resolver
, newSize
);
229 resolver
->n_attribute
= htonl(ntohl(resolver
->n_attribute
) + newLen
);
231 // add attribute [header]
233 header
= (dns_attribute_t
*)&resolver
->attribute
[oldLen
];
234 header
->type
= htonl(attribute_type
);
235 header
->length
= htonl(newLen
);
237 // add attribute [data]
239 bcopy(attribute
, &header
->attribute
[0], attribute_length
);
240 for (i
= attribute_length
; i
< rounded_length
; i
++) {
241 header
->attribute
[i
] = 0;
244 *_resolver
= (dns_create_resolver_t
)resolver
;
250 _dns_resolver_set_domain(dns_create_resolver_t
*_resolver
, const char *domain
)
252 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_DOMAIN
, strlen(domain
) + 1, (void *)domain
);
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_set_port(dns_create_resolver_t
*_resolver
, uint16_t port
)
271 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
273 resolver
->resolver
.port
= htons(port
);
279 _dns_resolver_add_search(dns_create_resolver_t
*_resolver
, const char *search
)
281 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
283 resolver
->resolver
.n_search
= htonl(ntohl(resolver
->resolver
.n_search
) + 1);
284 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_SEARCH
, strlen(search
) + 1, (void *)search
);
290 _dns_resolver_add_sortaddr(dns_create_resolver_t
*_resolver
, dns_sortaddr_t
*sortaddr
)
292 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
294 resolver
->resolver
.n_sortaddr
= htonl(ntohl(resolver
->resolver
.n_sortaddr
) + 1);
295 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_SORTADDR
, sizeof(dns_sortaddr_t
), (void *)sortaddr
);
301 _dns_resolver_set_options(dns_create_resolver_t
*_resolver
, const char *options
)
303 _dns_resolver_add_attribute(_resolver
, RESOLVER_ATTRIBUTE_OPTIONS
, strlen(options
) + 1, (void *)options
);
309 _dns_resolver_set_timeout(dns_create_resolver_t
*_resolver
, uint32_t timeout
)
311 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
313 resolver
->resolver
.timeout
= htonl(timeout
);
319 _dns_resolver_set_order(dns_create_resolver_t
*_resolver
, uint32_t order
)
321 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;
323 resolver
->resolver
.search_order
= htonl(order
);
329 _dns_resolver_free(dns_create_resolver_t
*_resolver
)
331 _dns_resolver_buf_t
*resolver
= (_dns_resolver_buf_t
*)*_resolver
;