]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_create.c
configd-453.16.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_create.c
1 /*
2 * Copyright (c) 2004, 2006, 2009, 2011 Apple Inc. All rights reserved.
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 #include <CommonCrypto/CommonDigest.h>
29
30 #include "dnsinfo_create.h"
31 #include "dnsinfo_private.h"
32 #include "shared_dns_info.h"
33 #include "network_information_priv.h"
34
35
36 #define ROUNDUP(a, size) \
37 (((a) & ((size)-1)) ? (1 + ((a) | ((size)-1))) : (a))
38
39
40 /*
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.
44 */
45 #define INITIAL_CONFIGURATION_BUF_SIZE 8192
46 #define INITIAL_RESOLVER_BUF_SIZE 1024
47
48
49 /*
50 * DNS [configuration] buffer functions
51 */
52
53
54 dns_create_config_t
55 _dns_configuration_create()
56 {
57 _dns_config_buf_t *config;
58
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;
63 }
64
65
66 static void
67 config_add_attribute(dns_create_config_t *_config,
68 uint32_t attribute_type,
69 uint32_t attribute_length,
70 void *attribute,
71 uint32_t extra_padding)
72 {
73 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
74 dns_attribute_t *header;
75 int i;
76 uint32_t newLen;
77 uint32_t newSize;
78 uint32_t oldLen;
79 uint32_t rounded_length;
80
81 // add space
82
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);
89 }
90 config->n_attribute = htonl(ntohl(config->n_attribute) + newLen);
91
92 // increment additional padding that will be needed (later)
93 config->n_padding = htonl(ntohl(config->n_padding) + extra_padding);
94
95 // add attribute [header]
96
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);
101
102 // add attribute [data]
103
104 bcopy(attribute, &header->attribute[0], attribute_length);
105 for (i = attribute_length; i < rounded_length; i++) {
106 header->attribute[i] = 0;
107 }
108
109 *_config = (dns_create_config_t)config;
110 return;
111 }
112
113
114 void
115 _dns_configuration_add_resolver(dns_create_config_t *_config,
116 dns_create_resolver_t _resolver)
117 {
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;
121
122 /*
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.
126 */
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));
130 }
131 if (resolver->resolver.n_search != 0) {
132 padding += ntohl(resolver->resolver.n_search) * sizeof(DNS_PTR(char *, x));
133 }
134 if (resolver->resolver.n_sortaddr != 0) {
135 padding += ntohl(resolver->resolver.n_sortaddr) * sizeof(DNS_PTR(dns_sortaddr_t *, x));
136 }
137
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),
143 (void *)resolver,
144 padding);
145 } else {
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),
150 (void *)resolver,
151 padding);
152 }
153
154 return;
155 }
156
157 _Bool
158 _nwi_state_store(nwi_state* state)
159 {
160 mach_port_t server;
161 kern_return_t status;
162 dnsDataOut_t dataRef = (dnsDataOut_t) state;
163 mach_msg_type_number_t dataLen = state->size;
164
165 server = _dns_configuration_server_port();
166 if (server == MACH_PORT_NULL) {
167 return FALSE;
168 }
169
170 status = shared_nwi_stateSet(server, dataRef, dataLen);
171
172 (void) mach_port_deallocate(mach_task_self(), server);
173
174 if (status != KERN_SUCCESS) {
175 return FALSE;
176 }
177
178 return TRUE;
179 }
180
181
182 void
183 _dns_configuration_signature(dns_create_config_t *_config,
184 unsigned char *signature,
185 size_t signature_len)
186 {
187 bzero(signature, signature_len);
188
189 if (_config != NULL) {
190 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
191
192 if (config != NULL) {
193 CC_SHA1_CTX ctx;
194 unsigned char *sha1;
195 unsigned char sha1_buf[CC_SHA1_DIGEST_LENGTH];
196
197 sha1 = (signature_len >= CC_SHA1_DIGEST_LENGTH) ? signature : sha1_buf;
198 CC_SHA1_Init(&ctx);
199 CC_SHA1_Update(&ctx,
200 config,
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);
205 }
206 }
207 }
208
209 return;
210 }
211
212
213 _Bool
214 _dns_configuration_store(dns_create_config_t *_config)
215 {
216 dnsDataOut_t dataRef = NULL;
217 mach_msg_type_number_t dataLen = 0;
218 mach_port_t server;
219 kern_return_t status;
220
221 server = _dns_configuration_server_port();
222 if (server == MACH_PORT_NULL) {
223 return FALSE;
224 }
225
226 if (_config != NULL) {
227 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
228
229 if (config != NULL) {
230 dataRef = (dnsDataOut_t)config;
231 dataLen = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
232 }
233 }
234
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);
239 return FALSE;
240 }
241
242 return TRUE;
243 }
244
245
246 void
247 _dns_configuration_free(dns_create_config_t *_config)
248 {
249 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
250
251 free(config);
252 *_config = NULL;
253 return;
254 }
255
256
257 /*
258 * DNS resolver configuration functions
259 */
260
261 dns_create_resolver_t
262 _dns_resolver_create()
263 {
264 _dns_resolver_buf_t *buf;
265
266 buf = calloc(1, INITIAL_RESOLVER_BUF_SIZE);
267 // buf->n_attribute = 0;
268 return (dns_create_resolver_t)buf;
269 }
270
271
272 static void
273 _dns_resolver_add_attribute(dns_create_resolver_t *_resolver,
274 uint32_t attribute_type,
275 uint32_t attribute_length,
276 void *attribute)
277 {
278 dns_attribute_t *header;
279 int i;
280 uint32_t newLen;
281 uint32_t newSize;
282 uint32_t oldLen;
283 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
284 uint32_t rounded_length;
285
286 // add space
287
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);
294 }
295 resolver->n_attribute = htonl(ntohl(resolver->n_attribute) + newLen);
296
297 // add attribute [header]
298
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);
303
304 // add attribute [data]
305
306 bcopy(attribute, &header->attribute[0], attribute_length);
307 for (i = attribute_length; i < rounded_length; i++) {
308 header->attribute[i] = 0;
309 }
310
311 *_resolver = (dns_create_resolver_t)resolver;
312 return;
313 }
314
315
316 void
317 _dns_resolver_add_nameserver(dns_create_resolver_t *_resolver, struct sockaddr *nameserver)
318 {
319 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
320
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);
323 return;
324 }
325
326
327 void
328 _dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
329 {
330 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
331
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);
334 return;
335 }
336
337
338 void
339 _dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
340 {
341 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
342
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);
345 return;
346 }
347
348
349 void
350 _dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
351 {
352 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_DOMAIN, strlen(domain) + 1, (void *)domain);
353 return;
354 }
355
356
357 void
358 _dns_resolver_set_flags(dns_create_resolver_t *_resolver, uint32_t flags)
359 {
360 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
361
362 resolver->resolver.flags = htonl(flags);
363 return;
364 }
365
366
367 void
368 _dns_resolver_set_if_index(dns_create_resolver_t *_resolver, uint32_t if_index)
369 {
370 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
371
372 resolver->resolver.if_index = htonl(if_index);
373 return;
374 }
375
376
377 void
378 _dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
379 {
380 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_OPTIONS, strlen(options) + 1, (void *)options);
381 return;
382 }
383
384
385 void
386 _dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
387 {
388 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
389
390 resolver->resolver.search_order = htonl(order);
391 return;
392 }
393
394
395 void
396 _dns_resolver_set_port(dns_create_resolver_t *_resolver, uint16_t port)
397 {
398 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
399
400 resolver->resolver.port = htons(port);
401 return;
402 }
403
404
405 void
406 _dns_resolver_set_reach_flags(dns_create_resolver_t *_resolver, uint32_t reach_flags)
407 {
408 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
409
410 resolver->resolver.reach_flags = htonl(reach_flags);
411 return;
412 }
413
414
415 void
416 _dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
417 {
418 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
419
420 resolver->resolver.timeout = htonl(timeout);
421 return;
422 }
423
424
425 void
426 _dns_resolver_free(dns_create_resolver_t *_resolver)
427 {
428 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
429
430 free(resolver);
431 *_resolver = NULL;
432 return;
433 }