]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_create.c
configd-204.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_create.c
1 /*
2 * Copyright (c) 2004, 2006 Apple Computer, 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
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
52 __private_extern__
53 dns_create_config_t
54 _dns_configuration_create()
55 {
56 _dns_config_buf_t *config;
57
58 config = calloc(1, INITIAL_CONFIGURATION_BUF_SIZE);
59 // config->n_attribute = 0;
60 // config->n_padding = 0;
61 return (dns_create_config_t)config;
62 }
63
64
65 static void
66 config_add_attribute(dns_create_config_t *_config,
67 uint32_t attribute_type,
68 uint32_t attribute_length,
69 void *attribute,
70 uint32_t extra_padding)
71 {
72 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
73 dns_attribute_t *header;
74 int i;
75 uint32_t newLen;
76 uint32_t newSize;
77 uint32_t oldLen;
78 uint32_t rounded_length;
79
80 // add space
81
82 oldLen = ntohl(config->n_attribute);
83 rounded_length = ROUNDUP(attribute_length, sizeof(uint32_t));
84 newLen = sizeof(dns_attribute_t) + rounded_length;
85 newSize = sizeof(_dns_config_buf_t) + oldLen + newLen;
86 if (newSize > INITIAL_CONFIGURATION_BUF_SIZE) {
87 config = realloc(config, newSize);
88 }
89 config->n_attribute = htonl(ntohl(config->n_attribute) + newLen);
90
91 // increment additional padding that will be needed (later)
92 config->n_padding = htonl(ntohl(config->n_padding) + extra_padding);
93
94 // add attribute [header]
95
96 header = (dns_attribute_t *)&config->attribute[oldLen];
97 header->type = htonl(attribute_type);
98 header->length = htonl(newLen);
99
100 // add attribute [data]
101
102 bcopy(attribute, &header->attribute[0], attribute_length);
103 for (i = attribute_length; i < rounded_length; i++) {
104 header->attribute[i] = 0;
105 }
106
107 *_config = (dns_create_config_t)config;
108 return;
109 }
110
111
112 __private_extern__
113 void
114 _dns_configuration_add_resolver(dns_create_config_t *_config,
115 dns_create_resolver_t _resolver)
116 {
117 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
118 uint32_t padding = 0;
119 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)_resolver;
120
121 /*
122 * compute the amount of space that will be needed for
123 * pointers to the resolver, the nameservers, the search
124 * list, and the sortaddr list.
125 */
126 padding += sizeof(DNS_PTR(dns_resolver_t *, x));
127 if (resolver->resolver.n_nameserver != 0) {
128 padding += ntohl(resolver->resolver.n_nameserver) * sizeof(DNS_PTR(struct sockaddr *, x));
129 }
130 if (resolver->resolver.n_search != 0) {
131 padding += ntohl(resolver->resolver.n_search) * sizeof(DNS_PTR(char *, x));
132 }
133 if (resolver->resolver.n_sortaddr != 0) {
134 padding += ntohl(resolver->resolver.n_sortaddr) * sizeof(DNS_PTR(dns_sortaddr_t *, x));
135 }
136
137 config->config.n_resolver = htonl(ntohl(config->config.n_resolver) + 1);
138
139 config_add_attribute(_config,
140 CONFIG_ATTRIBUTE_RESOLVER,
141 sizeof(_dns_resolver_buf_t) + ntohl(resolver->n_attribute),
142 (void *)resolver,
143 padding);
144
145 return;
146 }
147
148
149 __private_extern__
150 _Bool
151 _dns_configuration_store(dns_create_config_t *_config)
152 {
153 dnsDataOut_t dataRef = NULL;
154 mach_msg_type_number_t dataLen = 0;
155 mach_port_t server;
156 kern_return_t status;
157
158 server = _dns_configuration_server_port();
159 if (server == MACH_PORT_NULL) {
160 return FALSE;
161 }
162
163 if (_config != NULL) {
164 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
165
166 if (config != NULL) {
167 dataRef = (dnsDataOut_t)config;
168 dataLen = sizeof(_dns_config_buf_t) + ntohl(config->n_attribute);
169 }
170 }
171
172 status = shared_dns_infoSet(server, dataRef, dataLen);
173 (void) mach_port_deallocate(mach_task_self(), server);
174 if (status != KERN_SUCCESS) {
175 mach_error("shared_dns_infoSet():", status);
176 return FALSE;
177 }
178
179 return TRUE;
180 }
181
182
183 __private_extern__
184 void
185 _dns_configuration_free(dns_create_config_t *_config)
186 {
187 _dns_config_buf_t *config = (_dns_config_buf_t *)*_config;
188
189 free(config);
190 *_config = NULL;
191 return;
192 }
193
194
195 /*
196 * DNS resolver configuration functions
197 */
198
199 __private_extern__
200 dns_create_resolver_t
201 _dns_resolver_create()
202 {
203 _dns_resolver_buf_t *buf;
204
205 buf = calloc(1, INITIAL_RESOLVER_BUF_SIZE);
206 // buf->n_attribute = 0;
207 return (dns_create_resolver_t)buf;
208 }
209
210
211 static void
212 _dns_resolver_add_attribute(dns_create_resolver_t *_resolver,
213 uint32_t attribute_type,
214 uint32_t attribute_length,
215 void *attribute)
216 {
217 dns_attribute_t *header;
218 int i;
219 uint32_t newLen;
220 uint32_t newSize;
221 uint32_t oldLen;
222 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
223 uint32_t rounded_length;
224
225 // add space
226
227 oldLen = ntohl(resolver->n_attribute);
228 rounded_length = ROUNDUP(attribute_length, sizeof(uint32_t));
229 newLen = sizeof(dns_attribute_t) + rounded_length;
230 newSize = sizeof(_dns_resolver_buf_t) + oldLen + newLen;
231 if (newSize > INITIAL_RESOLVER_BUF_SIZE) {
232 resolver = realloc(resolver, newSize);
233 }
234 resolver->n_attribute = htonl(ntohl(resolver->n_attribute) + newLen);
235
236 // add attribute [header]
237
238 header = (dns_attribute_t *)&resolver->attribute[oldLen];
239 header->type = htonl(attribute_type);
240 header->length = htonl(newLen);
241
242 // add attribute [data]
243
244 bcopy(attribute, &header->attribute[0], attribute_length);
245 for (i = attribute_length; i < rounded_length; i++) {
246 header->attribute[i] = 0;
247 }
248
249 *_resolver = (dns_create_resolver_t)resolver;
250 return;
251 }
252
253
254 __private_extern__
255 void
256 _dns_resolver_set_domain(dns_create_resolver_t *_resolver, const char *domain)
257 {
258 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_DOMAIN, strlen(domain) + 1, (void *)domain);
259 return;
260 }
261
262
263 __private_extern__
264 void
265 _dns_resolver_add_nameserver(dns_create_resolver_t *_resolver, struct sockaddr *nameserver)
266 {
267 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
268
269 resolver->resolver.n_nameserver = htonl(ntohl(resolver->resolver.n_nameserver) + 1);
270 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_ADDRESS, nameserver->sa_len, (void *)nameserver);
271 return;
272 }
273
274
275 __private_extern__
276 void
277 _dns_resolver_set_port(dns_create_resolver_t *_resolver, uint16_t port)
278 {
279 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
280
281 resolver->resolver.port = htons(port);
282 return;
283 }
284
285
286 __private_extern__
287 void
288 _dns_resolver_add_search(dns_create_resolver_t *_resolver, const char *search)
289 {
290 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
291
292 resolver->resolver.n_search = htonl(ntohl(resolver->resolver.n_search) + 1);
293 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SEARCH, strlen(search) + 1, (void *)search);
294 return;
295 }
296
297
298 __private_extern__
299 void
300 _dns_resolver_add_sortaddr(dns_create_resolver_t *_resolver, dns_sortaddr_t *sortaddr)
301 {
302 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
303
304 resolver->resolver.n_sortaddr = htonl(ntohl(resolver->resolver.n_sortaddr) + 1);
305 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_SORTADDR, sizeof(dns_sortaddr_t), (void *)sortaddr);
306 return;
307 }
308
309
310 __private_extern__
311 void
312 _dns_resolver_set_options(dns_create_resolver_t *_resolver, const char *options)
313 {
314 _dns_resolver_add_attribute(_resolver, RESOLVER_ATTRIBUTE_OPTIONS, strlen(options) + 1, (void *)options);
315 return;
316 }
317
318
319 __private_extern__
320 void
321 _dns_resolver_set_timeout(dns_create_resolver_t *_resolver, uint32_t timeout)
322 {
323 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
324
325 resolver->resolver.timeout = htonl(timeout);
326 return;
327 }
328
329
330 __private_extern__
331 void
332 _dns_resolver_set_order(dns_create_resolver_t *_resolver, uint32_t order)
333 {
334 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
335
336 resolver->resolver.search_order = htonl(order);
337 return;
338 }
339
340
341 __private_extern__
342 void
343 _dns_resolver_free(dns_create_resolver_t *_resolver)
344 {
345 _dns_resolver_buf_t *resolver = (_dns_resolver_buf_t *)*_resolver;
346
347 free(resolver);
348 *_resolver = NULL;
349 return;
350 }