]> git.saurik.com Git - apple/configd.git/blame - dnsinfo/dnsinfo_create.c
configd-395.11.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_create.c
CommitLineData
dbf6a266 1/*
a40a14f8 2 * Copyright (c) 2004, 2006, 2009 Apple Inc. All rights reserved.
dbf6a266
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <stdlib.h>
25#include <strings.h>
26#include <mach/mach.h>
27#include <mach/mach_error.h>
28
29#include "dnsinfo_create.h"
30#include "dnsinfo_private.h"
31#include "shared_dns_info.h"
32
33
34#define ROUNDUP(a, size) \
35 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
36
37
38/*
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.
42 */
43#define INITIAL_CONFIGURATION_BUF_SIZE 8192
44#define INITIAL_RESOLVER_BUF_SIZE 1024
45
46
47/*
48 * DNS [configuration] buffer functions
49 */
50
51
dbf6a266
A
52dns_create_config_t
53_dns_configuration_create()
54{
55 _dns_config_buf_t *config;
56
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;
61}
62
63
64static void
65config_add_attribute(dns_create_config_t *_config,
66 uint32_t attribute_type,
67 uint32_t attribute_length,
68 void *attribute,
69 uint32_t extra_padding)
70{
71 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
72 dns_attribute_t *header;
73 int i;
74 uint32_t newLen;
75 uint32_t newSize;
76 uint32_t oldLen;
77 uint32_t rounded_length;
78
79 // add space
80
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);
87 }
88 config->n_attribute = htonl(ntohl(config->n_attribute) + newLen);
89
90 // increment additional padding that will be needed (later)
91 config->n_padding = htonl(ntohl(config->n_padding) + extra_padding);
92
93 // add attribute [header]
94
95 header = (dns_attribute_t *)&config->attribute[oldLen];
96 header->type = htonl(attribute_type);
97 header->length = htonl(newLen);
98
99 // add attribute [data]
100
101 bcopy(attribute, &header->attribute[0], attribute_length);
102 for (i = attribute_length; i < rounded_length; i++) {
103 header->attribute[i] = 0;
104 }
105
106 *_config = (dns_create_config_t)config;
107 return;
108}
109
110
dbf6a266
A
111void
112_dns_configuration_add_resolver(dns_create_config_t *_config,
113 dns_create_resolver_t _resolver)
114{
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;
118
119 /*
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.
123 */
edebe297 124 padding += sizeof(DNS_PTR(dns_resolver_t *, x));
dbf6a266 125 if (resolver->resolver.n_nameserver != 0) {
edebe297 126 padding += ntohl(resolver->resolver.n_nameserver) * sizeof(DNS_PTR(struct sockaddr *, x));
dbf6a266
A
127 }
128 if (resolver->resolver.n_search != 0) {
edebe297 129 padding += ntohl(resolver->resolver.n_search) * sizeof(DNS_PTR(char *, x));
dbf6a266
A
130 }
131 if (resolver->resolver.n_sortaddr != 0) {
edebe297 132 padding += ntohl(resolver->resolver.n_sortaddr) * sizeof(DNS_PTR(dns_sortaddr_t *, x));
dbf6a266
A
133 }
134
6bb65964
A
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),
140 (void *)resolver,
141 padding);
142 } else {
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),
147 (void *)resolver,
148 padding);
149 }
dbf6a266
A
150
151 return;
152}
153
154
dbf6a266
A
155_Bool
156_dns_configuration_store(dns_create_config_t *_config)
157{
158 dnsDataOut_t dataRef = NULL;
159 mach_msg_type_number_t dataLen = 0;
160 mach_port_t server;
161 kern_return_t status;
162
163 server = _dns_configuration_server_port();
164 if (server == MACH_PORT_NULL) {
165 return FALSE;
166 }
167
168 if (_config != NULL) {
169 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
170
171 if (config != NULL) {
172 dataRef = (dnsDataOut_t)config;
173 dataLen = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
174 }
175 }
176
177 status = shared_dns_infoSet(server, dataRef, dataLen);
edebe297 178 (void) mach_port_deallocate(mach_task_self(), server);
dbf6a266
A
179 if (status != KERN_SUCCESS) {
180 mach_error("shared_dns_infoSet():", status);
181 return FALSE;
182 }
183
184 return TRUE;
185}
186
187
dbf6a266
A
188void
189_dns_configuration_free(dns_create_config_t *_config)
190{
191 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
192
193 free(config);
194 *_config = NULL;
195 return;
196}
197
198
199/*
200 * DNS resolver configuration functions
201 */
202
dbf6a266
A
203dns_create_resolver_t
204_dns_resolver_create()
205{
206 _dns_resolver_buf_t *buf;
207
208 buf = calloc(1, INITIAL_RESOLVER_BUF_SIZE);
209// buf->n_attribute = 0;
210 return (dns_create_resolver_t)buf;
211}
212
213
214static void
215_dns_resolver_add_attribute(dns_create_resolver_t *_resolver,
216 uint32_t attribute_type,
217 uint32_t attribute_length,
218 void *attribute)
219{
220 dns_attribute_t *header;
221 int i;
222 uint32_t newLen;
223 uint32_t newSize;
224 uint32_t oldLen;
225 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
226 uint32_t rounded_length;
227
228 // add space
229
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);
236 }
237 resolver->n_attribute = htonl(ntohl(resolver->n_attribute) + newLen);
238
239 // add attribute [header]
240
241 header = (dns_attribute_t *)&resolver->attribute[oldLen];
242 header->type = htonl(attribute_type);
243 header->length = htonl(newLen);
244
245 // add attribute [data]
246
247 bcopy(attribute, &header->attribute[0], attribute_length);
248 for (i = attribute_length; i < rounded_length; i++) {
249 header->attribute[i] = 0;
250 }
251
252 *_resolver = (dns_create_resolver_t)resolver;
253 return;
254}
255
256
dbf6a266 257void
6bb65964 258_dns_resolver_add_nameserver(dns_create_resolver_t *_resolver, struct sockaddr *nameserver)
dbf6a266 259{
6bb65964
A
260 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
261
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);
dbf6a266
A
264 return;
265}
266
267
dbf6a266 268void
6bb65964 269_dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
dbf6a266
A
270{
271 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
272
6bb65964
A
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);
dbf6a266
A
275 return;
276}
277
278
dbf6a266 279void
6bb65964 280_dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
dbf6a266 281{
6bb65964 282 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_DOMAIN, strlen(domain) + 1, (void *)domain);
dbf6a266
A
283 return;
284}
285
286
dbf6a266 287void
6bb65964 288_dns_resolver_set_flags(dns_create_resolver_t *_resolver, uint32_t flags)
dbf6a266
A
289{
290 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
291
6bb65964 292 resolver->resolver.flags = htonl(flags);
dbf6a266
A
293 return;
294}
295
296
dbf6a266 297void
6bb65964 298_dns_resolver_set_if_index(dns_create_resolver_t *_resolver, uint32_t if_index)
dbf6a266
A
299{
300 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
301
6bb65964 302 resolver->resolver.if_index = htonl(if_index);
dbf6a266
A
303 return;
304}
305
306
dbf6a266
A
307void
308_dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
309{
310 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_OPTIONS, strlen(options) + 1, (void *)options);
311 return;
312}
313
314
dbf6a266 315void
6bb65964 316_dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
dbf6a266
A
317{
318 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
319
6bb65964 320 resolver->resolver.search_order = htonl(order);
dbf6a266
A
321 return;
322}
323
324
dbf6a266 325void
6bb65964 326_dns_resolver_set_port(dns_create_resolver_t *_resolver, uint16_t port)
dbf6a266
A
327{
328 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
329
6bb65964
A
330 resolver->resolver.port = htons(port);
331 return;
332}
333
334
335void
336_dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
337{
338 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
339
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);
342 return;
343}
344
345
346void
347_dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
348{
349 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
350
351 resolver->resolver.timeout = htonl(timeout);
dbf6a266
A
352 return;
353}
354
355
dbf6a266
A
356void
357_dns_resolver_free(dns_create_resolver_t *_resolver)
358{
359 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
360
361 free(resolver);
362 *_resolver = NULL;
363 return;
364}