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