2 * Copyright (c) 2013, 2015 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #ifndef _S_DNSINFO_INTERNAL_H
25 #define _S_DNSINFO_INTERNAL_H
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 "SCNetworkReachabilityInternal.h"
33 #include <arpa/inet.h>
36 #include "dnsinfo_private.h"
43 #define MY_LOG_DEFINED_LOCALLY
44 #define my_log(__level, fmt, ...) SC_log(__level, fmt, ## __VA_ARGS__)
48 #define DNS_CONFIG_BUF_MAX 1024*1024
52 * claim space for a list [of pointers] from the expanded DNS configuration padding
54 static __inline__ boolean_t
55 __dns_configuration_expand_add_list(void **padding
, uint32_t *n_padding
, int32_t count
, int32_t size
, void **list
)
60 if (need
> *n_padding
) {
64 *list
= (need
== 0) ? NULL
: *padding
;
72 * expand a DNS "resolver" from the provided buffer
74 static __inline__ dns_resolver_t
*
75 _dns_configuration_expand_resolver(_dns_resolver_buf_t
*buf
, uint32_t n_buf
, void **padding
, uint32_t *n_padding
)
77 dns_attribute_t
*attribute
;
79 int32_t n_nameserver
= 0;
81 int32_t n_sortaddr
= 0;
82 dns_resolver_t
*resolver
= (dns_resolver_t
*)&buf
->resolver
;
84 if (n_buf
< sizeof(_dns_resolver_buf_t
)) {
90 resolver
->domain
= NULL
;
92 // initialize nameserver list
94 resolver
->n_nameserver
= ntohl(resolver
->n_nameserver
);
95 if (!__dns_configuration_expand_add_list(padding
,
97 resolver
->n_nameserver
,
98 sizeof(DNS_PTR(struct sockaddr
*, x
)),
99 (void **)&resolver
->nameserver
)) {
105 resolver
->port
= ntohs(resolver
->port
);
107 // initialize search list
109 resolver
->n_search
= ntohl(resolver
->n_search
);
110 if (!__dns_configuration_expand_add_list(padding
,
113 sizeof(DNS_PTR(char *, x
)),
114 (void **)&resolver
->search
)) {
118 // initialize sortaddr list
120 resolver
->n_sortaddr
= ntohl(resolver
->n_sortaddr
);
121 if (!__dns_configuration_expand_add_list(padding
,
123 resolver
->n_sortaddr
,
124 sizeof(DNS_PTR(dns_sortaddr_t
*, x
)),
125 (void **)&resolver
->sortaddr
)) {
129 // initialize options
131 resolver
->options
= NULL
;
133 // initialize timeout
135 resolver
->timeout
= ntohl(resolver
->timeout
);
137 // initialize search_order
139 resolver
->search_order
= ntohl(resolver
->search_order
);
141 // initialize if_index
143 resolver
->if_index
= ntohl(resolver
->if_index
);
145 // initialize service_identifier
147 resolver
->service_identifier
= ntohl(resolver
->service_identifier
);
151 resolver
->flags
= ntohl(resolver
->flags
);
153 // initialize SCNetworkReachability flags
155 resolver
->reach_flags
= ntohl(resolver
->reach_flags
);
157 // process resolver buffer "attribute" data
159 n_attribute
= n_buf
- sizeof(_dns_resolver_buf_t
);
160 /* ALIGN: alignment not assumed, using accessors */
161 attribute
= (dns_attribute_t
*)(void *)&buf
->attribute
[0];
162 if (n_attribute
!= ntohl(buf
->n_attribute
)) {
166 while (n_attribute
>= sizeof(dns_attribute_t
)) {
167 uint32_t attribute_length
= ntohl(attribute
->length
);
169 switch (ntohl(attribute
->type
)) {
170 case RESOLVER_ATTRIBUTE_DOMAIN
:
171 resolver
->domain
= (char *)&attribute
->attribute
[0];
174 case RESOLVER_ATTRIBUTE_ADDRESS
:
175 if (resolver
->nameserver
== NULL
) {
178 resolver
->nameserver
[n_nameserver
++] = (struct sockaddr
*)&attribute
->attribute
[0];
181 case RESOLVER_ATTRIBUTE_SEARCH
:
182 if (resolver
->search
== NULL
) {
185 resolver
->search
[n_search
++] = (char *)&attribute
->attribute
[0];
188 case RESOLVER_ATTRIBUTE_SORTADDR
:
189 if (resolver
->sortaddr
== NULL
) {
192 resolver
->sortaddr
[n_sortaddr
++] = (dns_sortaddr_t
*)(void *)&attribute
->attribute
[0];
195 case RESOLVER_ATTRIBUTE_OPTIONS
:
196 resolver
->options
= (char *)&attribute
->attribute
[0];
199 case RESOLVER_ATTRIBUTE_CONFIGURATION_ID
:
200 resolver
->cid
= (char *)&attribute
->attribute
[0];
207 attribute
= (dns_attribute_t
*)((void *)attribute
+ attribute_length
);
208 n_attribute
-= attribute_length
;
211 if ((n_nameserver
!= resolver
->n_nameserver
) ||
212 (n_search
!= resolver
->n_search
) ||
213 (n_sortaddr
!= resolver
->n_sortaddr
)) {
226 * expand a DNS "configuration" from the provided buffer
228 static __inline__ dns_config_t
*
229 _dns_configuration_expand_config(_dns_config_buf_t
*buf
)
231 dns_attribute_t
*attribute
;
232 dns_config_t
*config
= (dns_config_t
*)buf
;
233 uint32_t n_attribute
;
235 int32_t n_resolver
= 0;
236 int32_t n_scoped_resolver
= 0;
237 int32_t n_service_specific_resolver
= 0;
240 n_attribute
= ntohl(buf
->n_attribute
); // pre-validated (or known OK) at entry
241 n_padding
= ntohl(buf
->n_padding
); // pre-validated (or known OK) at entry
243 // establish the start of padding to be after the last attribute
245 padding
= &buf
->attribute
[n_attribute
];
247 // initialize resolver lists
249 config
->n_resolver
= ntohl(config
->n_resolver
);
250 if (!__dns_configuration_expand_add_list(&padding
,
253 sizeof(DNS_PTR(dns_resolver_t
*, x
)),
254 (void **)&config
->resolver
)) {
258 config
->n_scoped_resolver
= ntohl(config
->n_scoped_resolver
);
259 if (!__dns_configuration_expand_add_list(&padding
,
261 config
->n_scoped_resolver
,
262 sizeof(DNS_PTR(dns_resolver_t
*, x
)),
263 (void **)&config
->scoped_resolver
)) {
267 config
->n_service_specific_resolver
= ntohl(config
->n_service_specific_resolver
);
268 if (!__dns_configuration_expand_add_list(&padding
,
270 config
->n_service_specific_resolver
,
271 sizeof(DNS_PTR(dns_resolver_t
*, x
)),
272 (void **)&config
->service_specific_resolver
)) {
276 // process configuration buffer "attribute" data
278 attribute
= (dns_attribute_t
*)(void *)&buf
->attribute
[0];
280 while (n_attribute
>= sizeof(dns_attribute_t
)) {
281 uint32_t attribute_length
= ntohl(attribute
->length
);
282 uint32_t attribute_type
= ntohl(attribute
->type
);
284 switch (attribute_type
) {
285 case CONFIG_ATTRIBUTE_RESOLVER
:
286 case CONFIG_ATTRIBUTE_SCOPED_RESOLVER
:
287 case CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER
: {
288 dns_resolver_t
*resolver
;
290 // expand resolver buffer
292 resolver
= _dns_configuration_expand_resolver((_dns_resolver_buf_t
*)(void *)&attribute
->attribute
[0],
293 attribute_length
- sizeof(dns_attribute_t
),
296 if (resolver
== NULL
) {
300 // add resolver to config list
302 if (attribute_type
== CONFIG_ATTRIBUTE_RESOLVER
) {
303 if (config
->resolver
== NULL
) {
306 config
->resolver
[n_resolver
++] = resolver
;
307 } else if (attribute_type
== CONFIG_ATTRIBUTE_SCOPED_RESOLVER
) {
308 if (config
->scoped_resolver
== NULL
) {
311 config
->scoped_resolver
[n_scoped_resolver
++] = resolver
;
312 } else if (attribute_type
== CONFIG_ATTRIBUTE_SERVICE_SPECIFIC_RESOLVER
) {
313 if (config
->service_specific_resolver
== NULL
) {
316 config
->service_specific_resolver
[n_service_specific_resolver
++] = resolver
;
326 attribute
= (dns_attribute_t
*)((void *)attribute
+ attribute_length
);
327 n_attribute
-= attribute_length
;
330 if (n_resolver
!= config
->n_resolver
) {
334 if (n_scoped_resolver
!= config
->n_scoped_resolver
) {
338 if (n_service_specific_resolver
!= config
->n_service_specific_resolver
) {
350 static __inline__
void
351 _dns_resolver_log(dns_resolver_t
*resolver
, int index
, Boolean debug
)
355 CFMutableStringRef str
;
357 my_log(LOG_INFO
, "\nresolver #%d", index
);
359 if (resolver
->domain
!= NULL
) {
360 my_log(LOG_INFO
, " domain : %s", resolver
->domain
);
363 for (i
= 0; i
< resolver
->n_search
; i
++) {
364 my_log(LOG_INFO
, " search domain[%d] : %s", i
, resolver
->search
[i
]);
367 for (i
= 0; i
< resolver
->n_nameserver
; i
++) {
370 _SC_sockaddr_to_string(resolver
->nameserver
[i
], buf
, sizeof(buf
));
371 my_log(LOG_INFO
, " nameserver[%d] : %s", i
, buf
);
374 for (i
= 0; i
< resolver
->n_sortaddr
; i
++) {
378 (void)inet_ntop(AF_INET
, &resolver
->sortaddr
[i
]->address
, abuf
, sizeof(abuf
));
379 (void)inet_ntop(AF_INET
, &resolver
->sortaddr
[i
]->mask
, mbuf
, sizeof(mbuf
));
380 my_log(LOG_INFO
, " sortaddr[%d] : %s/%s", i
, abuf
, mbuf
);
383 if (resolver
->options
!= NULL
) {
384 my_log(LOG_INFO
, " options : %s", resolver
->options
);
387 if (resolver
->port
!= 0) {
388 my_log(LOG_INFO
, " port : %hd", resolver
->port
);
391 if (resolver
->timeout
!= 0) {
392 my_log(LOG_INFO
, " timeout : %d", resolver
->timeout
);
395 if (resolver
->if_index
!= 0) {
399 if_name
= if_indextoname(resolver
->if_index
, buf
);
400 my_log(LOG_INFO
, " if_index : %d (%s)",
402 (if_name
!= NULL
) ? if_name
: "?");
405 if (resolver
->service_identifier
!= 0) {
406 my_log(LOG_INFO
, " service_identifier : %d",
407 resolver
->service_identifier
);
410 flags
= resolver
->flags
;
411 str
= CFStringCreateMutable(NULL
, 0);
412 CFStringAppend(str
, CFSTR(" flags : "));
414 CFStringAppendFormat(str
, NULL
, CFSTR("0x%08x ("), flags
);
416 if (flags
& DNS_RESOLVER_FLAGS_SCOPED
) {
417 flags
&= ~DNS_RESOLVER_FLAGS_SCOPED
;
418 CFStringAppendFormat(str
, NULL
, CFSTR("Scoped%s"), flags
!= 0 ? ", " : "");
420 if (flags
& DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC
) {
421 flags
&= ~DNS_RESOLVER_FLAGS_SERVICE_SPECIFIC
;
422 CFStringAppendFormat(str
, NULL
, CFSTR("Service-specific%s"), flags
!= 0 ? ", " : "");
424 if (flags
& DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS
) {
425 flags
&= ~DNS_RESOLVER_FLAGS_REQUEST_A_RECORDS
;
426 CFStringAppendFormat(str
, NULL
, CFSTR("Request A records%s"), flags
!= 0 ? ", " : "");
428 if (flags
& DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS
) {
429 flags
&= ~DNS_RESOLVER_FLAGS_REQUEST_AAAA_RECORDS
;
430 CFStringAppendFormat(str
, NULL
, CFSTR("Request AAAA records%s"), flags
!= 0 ? ", " : "");
433 CFStringAppendFormat(str
, NULL
, CFSTR("0x%08x"), flags
);
436 CFStringAppend(str
, CFSTR(")"));
438 my_log(LOG_INFO
, "%@", str
);
441 str
= (CFMutableStringRef
)__SCNetworkReachabilityCopyFlags(resolver
->reach_flags
,
444 my_log(LOG_INFO
, "%@", str
);
447 if (resolver
->search_order
!= 0) {
448 my_log(LOG_INFO
, " order : %d", resolver
->search_order
);
451 if (debug
&& (resolver
->cid
!= NULL
)) {
452 my_log(LOG_INFO
, " config id: %s", resolver
->cid
);
459 static __inline__
void
460 _dns_configuration_log(dns_config_t
*dns_config
, Boolean debug
)
464 my_log(LOG_INFO
, "DNS configuration");
466 for (i
= 0; i
< dns_config
->n_resolver
; i
++) {
467 dns_resolver_t
*resolver
= dns_config
->resolver
[i
];
469 _dns_resolver_log(resolver
, i
+ 1, debug
);
472 if ((dns_config
->n_scoped_resolver
> 0) && (dns_config
->scoped_resolver
!= NULL
)) {
473 my_log(LOG_INFO
, "\nDNS configuration (for scoped queries)");
475 for (i
= 0; i
< dns_config
->n_scoped_resolver
; i
++) {
476 dns_resolver_t
*resolver
= dns_config
->scoped_resolver
[i
];
478 _dns_resolver_log(resolver
, i
+ 1, debug
);
482 if ((dns_config
->n_service_specific_resolver
> 0) && (dns_config
->service_specific_resolver
!= NULL
)) {
483 my_log(LOG_INFO
, "\nDNS configuration (for service-specific queries)");
485 for (i
= 0; i
< dns_config
->n_service_specific_resolver
; i
++) {
486 dns_resolver_t
*resolver
= dns_config
->service_specific_resolver
[i
];
488 _dns_resolver_log(resolver
, i
+ 1, debug
);
496 #ifdef MY_LOG_DEFINED_LOCALLY
498 #undef MY_LOG_DEFINED_LOCALLY
499 #endif // MY_LOG_DEFINED_LOCALLY
504 #endif /* !_S_DNSINFO_INTERNAL_H */