2 * Copyright (c) 2004, 2006, 2008-2013, 2015-2017, 2019 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>
40 #define my_log(__level, __format, ...) os_log(OS_LOG_DEFAULT, __format, ## __VA_ARGS__)
41 #endif // SC_LOG_HANDLE
43 #include "libSystemConfiguration_client.h"
45 #include "dnsinfo_private.h"
46 #include "dnsinfo_internal.h"
50 dns_configuration_notify_key()
54 key
= "com.apple.system.SystemConfiguration.dns_configuration";
60 #pragma mark DNS configuration [dnsinfo] client support
63 // Note: protected by __dns_configuration_queue()
64 static int dnsinfo_active
= 0;
65 static libSC_info_client_t
*dnsinfo_client
= NULL
;
68 static dispatch_queue_t
69 __dns_configuration_queue()
71 static dispatch_once_t once
;
72 static dispatch_queue_t q
;
74 dispatch_once(&once
, ^{
75 q
= dispatch_queue_create(DNSINFO_SERVICE_NAME
, NULL
);
83 dns_configuration_copy()
85 dns_config_t
*dns_config
= NULL
;
86 _dns_config_buf_t
*dns_config_buf
= NULL
;
87 static const char *proc_name
= NULL
;
91 if (!libSC_info_available()) {
92 os_log(OS_LOG_DEFAULT
, "*** DNS configuration requested between fork() and exec()");
96 dispatch_sync(__dns_configuration_queue(), ^{
97 if ((dnsinfo_active
++ == 0) || (dnsinfo_client
== NULL
)) {
98 static dispatch_once_t once
;
99 static const char *service_name
= DNSINFO_SERVICE_NAME
;
101 dispatch_once(&once
, ^{
105 // get [XPC] service name
106 name
= getenv(service_name
);
108 service_name
= strdup(name
);
113 proc_name
= getprogname();
117 libSC_info_client_create(__dns_configuration_queue(), // dispatch queue
118 service_name
, // XPC service name
119 "DNS configuration"); // service description
120 if (dnsinfo_client
== NULL
) {
126 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
127 // if DNS configuration server not available
132 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
135 if (proc_name
!= NULL
) {
136 xpc_dictionary_set_string(reqdict
, DNSINFO_PROC_NAME
, proc_name
);
140 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_COPY
);
142 // send request to the DNS configuration server
143 reply
= libSC_send_message_with_reply_sync(dnsinfo_client
, reqdict
);
144 xpc_release(reqdict
);
150 dataRef
= xpc_dictionary_get_data(reply
, DNSINFO_CONFIGURATION
, &dataLen
);
151 if ((dataRef
!= NULL
) &&
152 ((dataLen
>= sizeof(_dns_config_buf_t
)) && (dataLen
<= DNS_CONFIG_BUF_MAX
))) {
153 dns_config_buf
= _dns_configuration_buffer_create(dataRef
, dataLen
);
159 if (dns_config_buf
!= NULL
) {
160 dns_config
= _dns_configuration_buffer_expand(dns_config_buf
);
161 if (dns_config
== NULL
) {
162 // if we were unable to expand the configuration
163 _dns_configuration_buffer_free(&dns_config_buf
);
172 dns_configuration_free(dns_config_t
*config
)
174 if (config
== NULL
) {
178 dispatch_sync(__dns_configuration_queue(), ^{
179 if (--dnsinfo_active
== 0) {
180 // if last reference, drop connection
181 libSC_info_client_release(dnsinfo_client
);
182 dnsinfo_client
= NULL
;
186 free((void *)config
);
192 _dns_configuration_ack(dns_config_t
*config
, const char *bundle_id
)
194 #pragma unused(bundle_id)
195 xpc_object_t reqdict
;
197 if (config
== NULL
) {
201 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
202 // if DNS configuration server not available
206 dispatch_sync(__dns_configuration_queue(), ^{
207 dnsinfo_active
++; // keep connection active (for the life of the process)
211 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
214 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_ACKNOWLEDGE
);
217 xpc_dictionary_set_uint64(reqdict
, DNSINFO_GENERATION
, config
->generation
);
219 // send acknowledgement to the DNS configuration server
220 xpc_connection_send_message(dnsinfo_client
->connection
, reqdict
);
222 xpc_release(reqdict
);
229 main(int argc
, char **argv
)
231 dns_config_t
*config
;
233 config
= dns_configuration_copy();
234 if (config
!= NULL
) {
235 dns_configuration_free(config
);