]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_copy.c
configd-204.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_copy.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 /*
25 * Modification History
26 *
27 * March 9, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31 #include <stdlib.h>
32 #include <mach/mach.h>
33 #include <mach/mach_error.h>
34
35 #include "dnsinfo.h"
36 #include "dnsinfo_private.h"
37 #include "shared_dns_info.h"
38
39
40 static boolean_t
41 add_list(void **padding, uint32_t *n_padding, int32_t count, int32_t size, void **list)
42 {
43 int32_t need;
44
45 need = count * size;
46 if (need > *n_padding) {
47 return FALSE;
48 }
49
50 *list = (need == 0) ? NULL : *padding;
51 *padding += need;
52 *n_padding -= need;
53 return TRUE;
54 }
55
56
57 static _dns_config_buf_t *
58 copy_dns_info()
59 {
60 uint8_t *buf = NULL;
61 dnsDataOut_t dataRef = NULL;
62 mach_msg_type_number_t dataLen = 0;
63 mach_port_t server;
64 kern_return_t status;
65
66 server = _dns_configuration_server_port();
67 if (server == MACH_PORT_NULL) {
68 return NULL;
69 }
70
71 status = shared_dns_infoGet(server, &dataRef, &dataLen);
72 (void)mach_port_deallocate(mach_task_self(), server);
73 if (status != KERN_SUCCESS) {
74 mach_error("shared_dns_infoGet():", status);
75 return NULL;
76 }
77
78 if (dataRef != NULL) {
79 if (dataLen >= sizeof(_dns_config_buf_t)) {
80 _dns_config_buf_t *config = (_dns_config_buf_t *)dataRef;
81 uint32_t len;
82 uint32_t n_padding = ntohl(config->n_padding);
83
84 len = dataLen + n_padding;
85 buf = malloc(len);
86 bcopy((void *)dataRef, buf, dataLen);
87 bzero(&buf[dataLen], n_padding);
88 }
89
90 status = vm_deallocate(mach_task_self(), (vm_address_t)dataRef, dataLen);
91 if (status != KERN_SUCCESS) {
92 mach_error("vm_deallocate():", status);
93 free(buf);
94 return NULL;
95 }
96 }
97
98 return (_dns_config_buf_t *)buf;
99 }
100
101
102 static dns_resolver_t *
103 expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32_t *n_padding)
104 {
105 dns_attribute_t *attribute;
106 uint32_t n_attribute;
107 int32_t n_nameserver = 0;
108 int32_t n_search = 0;
109 int32_t n_sortaddr = 0;
110 dns_resolver_t *resolver = (dns_resolver_t *)&buf->resolver;
111
112 if (n_buf < sizeof(_dns_resolver_buf_t)) {
113 goto error;
114 }
115
116 // initialize domain
117
118 resolver->domain = NULL;
119
120 // initialize nameserver list
121
122 resolver->n_nameserver = ntohl(resolver->n_nameserver);
123 if (!add_list(padding,
124 n_padding,
125 resolver->n_nameserver,
126 sizeof(DNS_PTR(struct sockaddr *, x)),
127 (void **)&resolver->nameserver)) {
128 goto error;
129 }
130
131 // initialize port
132
133 resolver->port = ntohs(resolver->port);
134
135 // initialize search list
136
137 resolver->n_search = ntohl(resolver->n_search);
138 if (!add_list(padding,
139 n_padding,
140 resolver->n_search,
141 sizeof(DNS_PTR(char *, x)),
142 (void **)&resolver->search)) {
143 goto error;
144 }
145
146 // initialize sortaddr list
147
148 resolver->n_sortaddr = ntohl(resolver->n_sortaddr);
149 if (!add_list(padding,
150 n_padding,
151 resolver->n_sortaddr,
152 sizeof(DNS_PTR(dns_sortaddr_t *, x)),
153 (void **)&resolver->sortaddr)) {
154 goto error;
155 }
156
157 // initialize options
158
159 resolver->options = NULL;
160
161 // initialize timeout
162
163 resolver->timeout = ntohl(resolver->timeout);
164
165 // initialize search_order
166
167 resolver->search_order = ntohl(resolver->search_order);
168
169 // process resolver buffer "attribute" data
170
171 n_attribute = n_buf - sizeof(_dns_resolver_buf_t);
172 attribute = (dns_attribute_t *)&buf->attribute[0];
173 if (n_attribute != ntohl(buf->n_attribute)) {
174 goto error;
175 }
176
177 while (n_attribute >= sizeof(dns_attribute_t)) {
178 int32_t attribute_length = ntohl(attribute->length);
179
180 switch (ntohl(attribute->type)) {
181 case RESOLVER_ATTRIBUTE_DOMAIN :
182 resolver->domain = (char *)&attribute->attribute[0];
183 break;
184
185 case RESOLVER_ATTRIBUTE_ADDRESS :
186 resolver->nameserver[n_nameserver++] = (struct sockaddr *)&attribute->attribute[0];
187 break;
188
189 case RESOLVER_ATTRIBUTE_SEARCH :
190 resolver->search[n_search++] = (char *)&attribute->attribute[0];
191 break;
192
193 case RESOLVER_ATTRIBUTE_SORTADDR :
194 resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)&attribute->attribute[0];
195 break;
196
197 case RESOLVER_ATTRIBUTE_OPTIONS :
198 resolver->options = (char *)&attribute->attribute[0];
199 break;
200
201 default :
202 break;
203 }
204
205 attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
206 n_attribute -= attribute_length;
207 }
208
209 if ((n_nameserver != resolver->n_nameserver) ||
210 (n_search != resolver->n_search ) ||
211 (n_sortaddr != resolver->n_sortaddr )) {
212 goto error;
213 }
214
215 return resolver;
216
217 error :
218
219 return NULL;
220 }
221
222
223 static dns_config_t *
224 expand_config(_dns_config_buf_t *buf)
225 {
226 dns_attribute_t *attribute;
227 dns_config_t *config = (dns_config_t *)buf;
228 uint32_t n_attribute;
229 uint32_t n_padding;
230 int32_t n_resolver = 0;
231 void *padding;
232
233 // establish padding
234
235 padding = &buf->attribute[ntohl(buf->n_attribute)];
236 n_padding = ntohl(buf->n_padding);
237
238 // initialize resolver list
239
240 config->n_resolver = ntohl(config->n_resolver);
241 if (!add_list(&padding,
242 &n_padding,
243 config->n_resolver,
244 sizeof(DNS_PTR(dns_resolver_t *, x)),
245 (void **)&config->resolver)) {
246 goto error;
247 }
248
249 // process configuration buffer "attribute" data
250
251 n_attribute = ntohl(buf->n_attribute);
252 attribute = (dns_attribute_t *)&buf->attribute[0];
253
254 while (n_attribute >= sizeof(dns_attribute_t)) {
255 int32_t attribute_length = ntohl(attribute->length);
256
257 switch (ntohl(attribute->type)) {
258 case CONFIG_ATTRIBUTE_RESOLVER : {
259 dns_resolver_t *resolver;
260
261 // expand resolver buffer
262
263 resolver = expand_resolver((_dns_resolver_buf_t *)&attribute->attribute[0],
264 attribute_length - sizeof(dns_attribute_t),
265 &padding,
266 &n_padding);
267 if (resolver == NULL) {
268 goto error;
269 }
270
271 // add resolver to config list
272
273 config->resolver[n_resolver++] = resolver;
274
275 break;
276 }
277
278 default :
279 break;
280 }
281
282 attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
283 n_attribute -= attribute_length;
284 }
285
286 if (n_resolver != config->n_resolver) {
287 goto error;
288 }
289
290 return config;
291
292 error :
293
294 return NULL;
295 }
296
297
298 __private_extern__
299 const char *
300 dns_configuration_notify_key()
301 {
302 return _dns_configuration_notify_key();
303 }
304
305
306 __private_extern__
307 dns_config_t *
308 dns_configuration_copy()
309 {
310 _dns_config_buf_t *buf;
311 dns_config_t *config;
312
313 buf = copy_dns_info();
314 if (buf == NULL) {
315 return NULL;
316 }
317
318 config = expand_config(buf);
319 if (config == NULL) {
320 free(buf);
321 return NULL;
322 }
323
324 return config;
325 }
326
327
328 __private_extern__
329 void
330 dns_configuration_free(dns_config_t *config)
331 {
332 if (config == NULL) {
333 return;
334 }
335
336 free((void *)config);
337 return;
338 }