]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_internal.h
configd-963.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_internal.h
1 /*
2 * Copyright (c) 2013, 2015-2017 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 #ifndef _S_DNSINFO_INTERNAL_H
25 #define _S_DNSINFO_INTERNAL_H
26
27 #include <Availability.h>
28 #include <TargetConditionals.h>
29 #include <sys/cdefs.h>
30 #include <SystemConfiguration/SystemConfiguration.h>
31 #include <SystemConfiguration/SCPrivate.h>
32 #include <arpa/inet.h>
33
34 #include <dnsinfo.h>
35 #include "dnsinfo_private.h"
36
37 #define DNS_CONFIG_BUF_MAX 1024*1024
38
39 __BEGIN_DECLS
40
41 #ifndef my_log
42 #define my_log(__level, __format, ...) SC_log(__level, __format, ## __VA_ARGS__)
43 #define MY_LOG_DEFINED_LOCALLY
44 #endif // !my_log
45
46 /*
47 * claim space for a list [of pointers] from the expanded DNS configuration padding
48 */
49 static __inline__ boolean_t
50 __dns_configuration_expand_add_list(void **padding, uint32_t *n_padding, uint32_t count, uint32_t size, void **list)
51 {
52 uint32_t need;
53
54 need = count * size;
55 if (need > *n_padding) {
56 return FALSE;
57 }
58
59 *list = (need == 0) ? NULL : *padding;
60 *padding += need;
61 *n_padding -= need;
62 return TRUE;
63 }
64
65
66 /*
67 * expand a DNS "resolver" from the provided buffer
68 */
69 static __inline__ dns_resolver_t *
70 _dns_configuration_expand_resolver(_dns_resolver_buf_t *buf, uint32_t n_buf, void **padding, uint32_t *n_padding)
71 {
72 dns_attribute_t *attribute;
73 uint32_t n_attribute;
74 int32_t n_nameserver = 0;
75 int32_t n_search = 0;
76 int32_t n_sortaddr = 0;
77 void *ptr;
78 dns_resolver_t *resolver = (dns_resolver_t *)&buf->resolver;
79
80 if (n_buf < sizeof(_dns_resolver_buf_t)) {
81 goto error;
82 }
83
84 // initialize domain
85
86 resolver->domain = NULL;
87
88 // initialize nameserver list
89
90 resolver->n_nameserver = ntohl(resolver->n_nameserver);
91 if (!__dns_configuration_expand_add_list(padding,
92 n_padding,
93 resolver->n_nameserver,
94 sizeof(DNS_PTR(struct sockaddr *, x)),
95 &ptr)) {
96 goto error;
97 }
98 resolver->nameserver = ptr;
99
100 // initialize port
101
102 resolver->port = ntohs(resolver->port);
103
104 // initialize search list
105
106 resolver->n_search = ntohl(resolver->n_search);
107 if (!__dns_configuration_expand_add_list(padding,
108 n_padding,
109 resolver->n_search,
110 sizeof(DNS_PTR(char *, x)),
111 &ptr)) {
112 goto error;
113 }
114 resolver->search = ptr;
115
116 // initialize sortaddr list
117
118 resolver->n_sortaddr = ntohl(resolver->n_sortaddr);
119 if (!__dns_configuration_expand_add_list(padding,
120 n_padding,
121 resolver->n_sortaddr,
122 sizeof(DNS_PTR(dns_sortaddr_t *, x)),
123 &ptr)) {
124 goto error;
125 }
126 resolver->sortaddr = ptr;
127
128 // initialize options
129
130 resolver->options = NULL;
131
132 // initialize timeout
133
134 resolver->timeout = ntohl(resolver->timeout);
135
136 // initialize search_order
137
138 resolver->search_order = ntohl(resolver->search_order);
139
140 // initialize if_index
141
142 resolver->if_index = ntohl(resolver->if_index);
143
144 // initialize service_identifier
145
146 resolver->service_identifier = ntohl(resolver->service_identifier);
147
148 // initialize flags
149
150 resolver->flags = ntohl(resolver->flags);
151
152 // initialize SCNetworkReachability flags
153
154 resolver->reach_flags = ntohl(resolver->reach_flags);
155
156 // process resolver buffer "attribute" data
157
158 n_attribute = n_buf - sizeof(_dns_resolver_buf_t);
159 /* ALIGN: alignment not assumed, using accessors */
160 attribute = (dns_attribute_t *)(void *)&buf->attribute[0];
161 if (n_attribute != ntohl(buf->n_attribute)) {
162 goto error;
163 }
164
165 while (n_attribute >= sizeof(dns_attribute_t)) {
166 uint32_t attribute_length = ntohl(attribute->length);
167
168 switch (ntohl(attribute->type)) {
169 case RESOLVER_ATTRIBUTE_DOMAIN :
170 resolver->domain = (char *)&attribute->attribute[0];
171 break;
172
173 case RESOLVER_ATTRIBUTE_ADDRESS :
174 if (resolver->nameserver == NULL) {
175 goto error;
176 }
177 resolver->nameserver[n_nameserver++] = (struct sockaddr *)&attribute->attribute[0];
178 break;
179
180 case RESOLVER_ATTRIBUTE_SEARCH :
181 if (resolver->search == NULL) {
182 goto error;
183 }
184 resolver->search[n_search++] = (char *)&attribute->attribute[0];
185 break;
186
187 case RESOLVER_ATTRIBUTE_SORTADDR :
188 if (resolver->sortaddr == NULL) {
189 goto error;
190 }
191 resolver->sortaddr[n_sortaddr++] = (dns_sortaddr_t *)(void *)&attribute->attribute[0];
192 break;
193
194 case RESOLVER_ATTRIBUTE_OPTIONS :
195 resolver->options = (char *)&attribute->attribute[0];
196 break;
197
198 case RESOLVER_ATTRIBUTE_CONFIGURATION_ID :
199 resolver->cid = (char *)&attribute->attribute[0];
200 break;
201
202 case RESOLVER_ATTRIBUTE_INTERFACE_NAME :
203 resolver->if_name = (char *)&attribute->attribute[0];
204 break;
205
206 default :
207 break;
208 }
209
210 attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
211 n_attribute -= attribute_length;
212 }
213
214 if ((n_nameserver != resolver->n_nameserver) ||
215 (n_search != resolver->n_search ) ||
216 (n_sortaddr != resolver->n_sortaddr )) {
217 goto error;
218 }
219
220 return resolver;
221
222 error :
223
224 return NULL;
225 }
226
227
228 /*
229 * initialize a DNS "configuration" buffer
230 */
231 static __inline__ _dns_config_buf_t *
232 _dns_configuration_buffer_create(const void *dataRef, size_t dataLen)
233 {
234 uint8_t *buf = NULL;
235 size_t bufLen;
236 _dns_config_buf_t *config = (_dns_config_buf_t *)dataRef;
237 size_t configLen;
238 uint32_t n_attribute = ntohl(config->n_attribute);
239 uint32_t n_padding = ntohl(config->n_padding);
240
241 /*
242 * Check that the size of the configuration header plus the size of the
243 * attribute data matches the size of the configuration buffer.
244 *
245 * If the sizes are different, something that should NEVER happen, CRASH!
246 */
247 configLen = sizeof(_dns_config_buf_t) + n_attribute;
248 #ifdef DEBUG
249 assert(configLen == dataLen);
250 #else // DEBUG
251 if (configLen != dataLen) {
252 my_log(LOG_ERR, "DNS configuration: size error (%zu != %zu)", configLen, dataLen);
253 return NULL;
254 }
255 #endif // DEBUG
256
257 /*
258 * Check that the size of the requested padding would not result in our
259 * allocating a configuration + padding buffer larger than our maximum size.
260 *
261 * If the requested padding size is too large, something that should NEVER
262 * happen, CRASH!
263 */
264 #ifdef DEBUG
265 assert(n_padding <= (DNS_CONFIG_BUF_MAX - dataLen));
266 #else // DEBUG
267 if (n_padding > (DNS_CONFIG_BUF_MAX - dataLen)) {
268 my_log(LOG_ERR, "DNS configuration: padding error (%u > %zu)",
269 n_padding,
270 (DNS_CONFIG_BUF_MAX - dataLen));
271 return NULL;
272 }
273 #endif // DEBUG
274
275 /*
276 * Check that the actual size of the configuration data and any requested
277 * padding will be less than the maximum possible size of the in-memory
278 * configuration buffer.
279 *
280 * If the length needed is too large, something that should NEVER happen, CRASH!
281 */
282 bufLen = dataLen + n_padding;
283 #ifdef DEBUG
284 assert(bufLen <= DNS_CONFIG_BUF_MAX);
285 #else // DEBUG
286 if (bufLen > DNS_CONFIG_BUF_MAX) {
287 my_log(LOG_ERR, "DNS configuration: length error (%zu > %u)",
288 bufLen,
289 DNS_CONFIG_BUF_MAX);
290 return NULL;
291 }
292 #endif // DEBUG
293
294 // allocate a buffer large enough to hold both the configuration
295 // data and the padding.
296 buf = malloc(bufLen);
297 bcopy((void *)dataRef, buf, dataLen);
298 bzero(&buf[dataLen], n_padding);
299
300 return (_dns_config_buf_t *)(void *)buf;
301 }
302
303
304 /*
305 * expand a DNS "configuration" from the provided buffer
306 */
307 static __inline__ void
308 _dns_configuration_buffer_free(_dns_config_buf_t **buf)
309 {
310 _dns_config_buf_t *config = (_dns_config_buf_t *)*buf;
311
312 free(config);
313 *buf = NULL;
314 return;
315 }
316
317
318 /*
319 * expand a DNS "configuration" from the provided buffer
320 */
321 static __inline__ dns_config_t *
322 _dns_configuration_buffer_expand(_dns_config_buf_t *buf)
323 {
324 dns_attribute_t *attribute;
325 dns_config_t *config = (dns_config_t *)buf;
326 uint32_t n_attribute;
327 uint32_t n_padding;
328 int32_t n_resolver = 0;
329 int32_t n_scoped_resolver = 0;
330 int32_t n_service_specific_resolver = 0;
331 void *padding;
332 void *ptr;
333
334 n_attribute = ntohl(buf->n_attribute); // pre-validated (or known OK) at entry
335 n_padding = ntohl(buf->n_padding); // pre-validated (or known OK) at entry
336
337 // establish the start of padding to be after the last attribute
338
339 padding = &buf->attribute[n_attribute];
340
341 // initialize resolver lists
342
343 config->n_resolver = ntohl(config->n_resolver);
344 if (!__dns_configuration_expand_add_list(&padding,
345 &n_padding,
346 config->n_resolver,
347 sizeof(DNS_PTR(dns_resolver_t *, x)),
348 &ptr)) {
349 goto error;
350 }
351 config->resolver = ptr;
352
353 config->n_scoped_resolver = ntohl(config->n_scoped_resolver);
354 if (!__dns_configuration_expand_add_list(&padding,
355 &n_padding,
356 config->n_scoped_resolver,
357 sizeof(DNS_PTR(dns_resolver_t *, x)),
358 &ptr)) {
359 goto error;
360 }
361 config->scoped_resolver = ptr;
362
363 config->n_service_specific_resolver = ntohl(config->n_service_specific_resolver);
364 if (!__dns_configuration_expand_add_list(&padding,
365 &n_padding,
366 config->n_service_specific_resolver,
367 sizeof(DNS_PTR(dns_resolver_t *, x)),
368 &ptr)) {
369 goto error;
370 }
371 config->service_specific_resolver = ptr;
372
373 // process configuration buffer "attribute" data
374
375 attribute = (dns_attribute_t *)(void *)&buf->attribute[0];
376
377 while (n_attribute >= sizeof(dns_attribute_t)) {
378 uint32_t attribute_length = ntohl(attribute->length);
379 uint32_t attribute_type = ntohl(attribute->type);
380
381 switch (attribute_type) {
382 case CONFIG_ATTRIBUTE_RESOLVER :
383 case CONFIG_ATTRIBUTE_SCOPED_RESOLVER :
384 case CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER : {
385 dns_resolver_t *resolver;
386
387 // expand resolver buffer
388
389 resolver = _dns_configuration_expand_resolver((_dns_resolver_buf_t *)(void *)&attribute->attribute[0],
390 attribute_length - sizeof(dns_attribute_t),
391 &padding,
392 &n_padding);
393 if (resolver == NULL) {
394 goto error;
395 }
396
397 // add resolver to config list
398
399 if (attribute_type == CONFIG_ATTRIBUTE_RESOLVER) {
400 if (config->resolver == NULL) {
401 goto error;
402 }
403 config->resolver[n_resolver++] = resolver;
404 } else if (attribute_type == CONFIG_ATTRIBUTE_SCOPED_RESOLVER) {
405 if (config->scoped_resolver == NULL) {
406 goto error;
407 }
408 config->scoped_resolver[n_scoped_resolver++] = resolver;
409 } else if (attribute_type == CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER) {
410 if (config->service_specific_resolver == NULL) {
411 goto error;
412 }
413 config->service_specific_resolver[n_service_specific_resolver++] = resolver;
414 }
415
416 break;
417 }
418
419 default :
420 break;
421 }
422
423 attribute = (dns_attribute_t *)((void *)attribute + attribute_length);
424 n_attribute -= attribute_length;
425 }
426
427 if (n_resolver != config->n_resolver) {
428 goto error;
429 }
430
431 if (n_scoped_resolver != config->n_scoped_resolver) {
432 goto error;
433 }
434
435 if (n_service_specific_resolver != config->n_service_specific_resolver) {
436 goto error;
437 }
438
439 return config;
440
441 error :
442
443 return NULL;
444 }
445
446 #ifdef MY_LOG_DEFINED_LOCALLY
447 #undef my_log
448 #undef MY_LOG_DEFINED_LOCALLY
449 #endif // MY_LOG_DEFINED_LOCALLY
450
451 __END_DECLS
452
453 #endif /* !_S_DNSINFO_INTERNAL_H */