2 * Copyright (c) 2004, 2006, 2008-2013, 2015-2017 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@
25 * Modification History
27 * March 9, 2004 Allan Nathanson <ajn@apple.com>
34 #include <dispatch/dispatch.h>
35 #include <mach/mach.h>
36 #ifdef VERBOSE_ACTIVITY_LOGGING
37 #include <os/activity.h>
38 #endif // VERBOSE_ACTIVITY_LOGGING
43 #define my_log(__level, __format, ...) os_log(OS_LOG_DEFAULT, __format, ## __VA_ARGS__)
44 #endif // SC_LOG_HANDLE
46 #include "libSystemConfiguration_client.h"
48 #include "dnsinfo_private.h"
49 #include "dnsinfo_internal.h"
53 dns_configuration_notify_key()
57 key
= "com.apple.system.SystemConfiguration.dns_configuration";
63 #pragma mark DNS configuration [dnsinfo] client support
66 // Note: protected by __dns_configuration_queue()
67 static int dnsinfo_active
= 0;
68 static libSC_info_client_t
*dnsinfo_client
= NULL
;
71 #ifdef VERBOSE_ACTIVITY_LOGGING
73 __dns_configuration_activity()
75 static os_activity_t activity
;
76 static dispatch_once_t once
;
78 dispatch_once(&once
, ^{
79 activity
= os_activity_create("accessing DNS configuration",
81 OS_ACTIVITY_FLAG_DEFAULT
);
86 #endif // VERBOSE_ACTIVITY_LOGGING
89 static dispatch_queue_t
90 __dns_configuration_queue()
92 static dispatch_once_t once
;
93 static dispatch_queue_t q
;
95 dispatch_once(&once
, ^{
96 q
= dispatch_queue_create(DNSINFO_SERVICE_NAME
, NULL
);
104 dns_configuration_copy()
106 dns_config_t
*dns_config
= NULL
;
107 _dns_config_buf_t
*dns_config_buf
= NULL
;
108 static const char *proc_name
= NULL
;
109 xpc_object_t reqdict
;
112 if (!libSC_info_available()) {
113 os_log(OS_LOG_DEFAULT
, "*** DNS configuration requested between fork() and exec()");
117 dispatch_sync(__dns_configuration_queue(), ^{
118 if ((dnsinfo_active
++ == 0) || (dnsinfo_client
== NULL
)) {
119 static dispatch_once_t once
;
120 static const char *service_name
= DNSINFO_SERVICE_NAME
;
122 dispatch_once(&once
, ^{
126 // get [XPC] service name
127 name
= getenv(service_name
);
129 service_name
= strdup(name
);
134 proc_name
= getprogname();
138 libSC_info_client_create(__dns_configuration_queue(), // dispatch queue
139 service_name
, // XPC service name
140 "DNS configuration"); // service description
141 if (dnsinfo_client
== NULL
) {
147 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
148 // if DNS configuration server not available
152 #ifdef VERBOSE_ACTIVITY_LOGGING
153 // scope DNS configuration activity
154 os_activity_scope(__dns_configuration_activity());
155 #endif // VERBOSE_ACTIVITY_LOGGING
158 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
161 if (proc_name
!= NULL
) {
162 xpc_dictionary_set_string(reqdict
, DNSINFO_PROC_NAME
, proc_name
);
166 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_COPY
);
168 // send request to the DNS configuration server
169 reply
= libSC_send_message_with_reply_sync(dnsinfo_client
, reqdict
);
170 xpc_release(reqdict
);
176 dataRef
= xpc_dictionary_get_data(reply
, DNSINFO_CONFIGURATION
, &dataLen
);
177 if ((dataRef
!= NULL
) &&
178 ((dataLen
>= sizeof(_dns_config_buf_t
)) && (dataLen
<= DNS_CONFIG_BUF_MAX
))) {
179 dns_config_buf
= _dns_configuration_buffer_create(dataRef
, dataLen
);
185 if (dns_config_buf
!= NULL
) {
186 dns_config
= _dns_configuration_buffer_expand(dns_config_buf
);
187 if (dns_config
== NULL
) {
188 // if we were unable to expand the configuration
189 _dns_configuration_buffer_free(&dns_config_buf
);
198 dns_configuration_free(dns_config_t
*config
)
200 if (config
== NULL
) {
204 dispatch_sync(__dns_configuration_queue(), ^{
205 if (--dnsinfo_active
== 0) {
206 // if last reference, drop connection
207 libSC_info_client_release(dnsinfo_client
);
208 dnsinfo_client
= NULL
;
212 free((void *)config
);
218 _dns_configuration_ack(dns_config_t
*config
, const char *bundle_id
)
220 #pragma unused(bundle_id)
221 xpc_object_t reqdict
;
223 if (config
== NULL
) {
227 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
228 // if DNS configuration server not available
232 dispatch_sync(__dns_configuration_queue(), ^{
233 dnsinfo_active
++; // keep connection active (for the life of the process)
237 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
240 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_ACKNOWLEDGE
);
243 xpc_dictionary_set_uint64(reqdict
, DNSINFO_GENERATION
, config
->generation
);
245 // send acknowledgement to the DNS configuration server
246 xpc_connection_send_message(dnsinfo_client
->connection
, reqdict
);
248 xpc_release(reqdict
);
255 main(int argc
, char **argv
)
257 dns_config_t
*config
;
259 config
= dns_configuration_copy();
260 if (config
!= NULL
) {
261 dns_configuration_free(config
);