2 * Copyright (c) 2004, 2006, 2008-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@
25 * Modification History
27 * March 9, 2004 Allan Nathanson <ajn@apple.com>
34 #include <mach/mach.h>
35 #include <mach/mach_error.h>
36 #include <dispatch/dispatch.h>
39 #include "libSystemConfiguration_client.h"
41 #include "dnsinfo_private.h"
42 #include "dnsinfo_internal.h"
46 dns_configuration_notify_key()
50 key
= "com.apple.system.SystemConfiguration.dns_configuration";
56 #pragma mark DNS configuration [dnsinfo] client support
59 // Note: protected by __dns_configuration_queue()
60 static int dnsinfo_active
= 0;
61 static libSC_info_client_t
*dnsinfo_client
= NULL
;
64 static dispatch_queue_t
65 __dns_configuration_queue()
67 static dispatch_once_t once
;
68 static dispatch_queue_t q
;
70 dispatch_once(&once
, ^{
71 q
= dispatch_queue_create(DNSINFO_SERVICE_NAME
, NULL
);
79 dns_configuration_copy()
83 dns_config_t
*config
= NULL
;
84 static const char *proc_name
= NULL
;
88 dispatch_sync(__dns_configuration_queue(), ^{
89 if ((dnsinfo_active
++ == 0) || (dnsinfo_client
== NULL
)) {
90 static dispatch_once_t once
;
91 static const char *service_name
= DNSINFO_SERVICE_NAME
;
93 dispatch_once(&once
, ^{
97 // get [XPC] service name
98 name
= getenv(service_name
);
100 service_name
= strdup(name
);
105 proc_name
= getprogname();
109 libSC_info_client_create(__dns_configuration_queue(), // dispatch queue
110 service_name
, // XPC service name
111 "DNS configuration"); // service description
112 if (dnsinfo_client
== NULL
) {
118 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
119 // if DNS configuration server not available
124 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
127 if (proc_name
!= NULL
) {
128 xpc_dictionary_set_string(reqdict
, DNSINFO_PROC_NAME
, proc_name
);
132 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_COPY
);
134 // send request to the DNS configuration server
135 reply
= libSC_send_message_with_reply_sync(dnsinfo_client
, reqdict
);
136 xpc_release(reqdict
);
142 dataRef
= xpc_dictionary_get_data(reply
, DNSINFO_CONFIGURATION
, &dataLen
);
143 if ((dataRef
!= NULL
) &&
144 ((dataLen
>= sizeof(_dns_config_buf_t
)) && (dataLen
<= DNS_CONFIG_BUF_MAX
))) {
145 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)(void *)dataRef
;
147 uint32_t n_attribute
= ntohl(config
->n_attribute
);
148 uint32_t n_padding
= ntohl(config
->n_padding
);
151 * Check that the size of the configuration header plus the size of the
152 * attribute data matches the size of the configuration buffer.
154 * If the sizes are different, something that should NEVER happen, CRASH!
156 configLen
= sizeof(_dns_config_buf_t
) + n_attribute
;
157 assert(configLen
== dataLen
);
160 * Check that the size of the requested padding would not result in our
161 * allocating a configuration + padding buffer larger than our maximum size.
163 * If the requested padding size is too large, something that should NEVER
166 assert(n_padding
<= (DNS_CONFIG_BUF_MAX
- dataLen
));
169 * Check that the actual size of the configuration data and any requested
170 * padding will be less than the maximum possible size of the in-memory
171 * configuration buffer.
173 * If the length needed is too large, something that should NEVER happen, CRASH!
175 bufLen
= dataLen
+ n_padding
;
176 assert(bufLen
<= DNS_CONFIG_BUF_MAX
);
178 // allocate a buffer large enough to hold both the configuration
179 // data and the padding.
180 buf
= malloc(bufLen
);
181 bcopy((void *)dataRef
, buf
, dataLen
);
182 bzero(&buf
[dataLen
], n_padding
);
189 /* ALIGN: cast okay since _dns_config_buf_t is int aligned */
190 config
= _dns_configuration_expand_config((_dns_config_buf_t
*)(void *)buf
);
191 if (config
== NULL
) {
201 dns_configuration_free(dns_config_t
*config
)
203 if (config
== NULL
) {
207 dispatch_sync(__dns_configuration_queue(), ^{
208 if (--dnsinfo_active
== 0) {
209 // if last reference, drop connection
210 libSC_info_client_release(dnsinfo_client
);
211 dnsinfo_client
= NULL
;
215 free((void *)config
);
221 _dns_configuration_ack(dns_config_t
*config
, const char *bundle_id
)
223 xpc_object_t reqdict
;
225 if (config
== NULL
) {
229 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
230 // if DNS configuration server not available
234 dispatch_sync(__dns_configuration_queue(), ^{
235 dnsinfo_active
++; // keep connection active (for the life of the process)
239 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
242 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_ACKNOWLEDGE
);
245 xpc_dictionary_set_uint64(reqdict
, DNSINFO_GENERATION
, config
->generation
);
247 // send acknowledgement to the DNS configuration server
248 xpc_connection_send_message(dnsinfo_client
->connection
, reqdict
);
250 xpc_release(reqdict
);
257 main(int argc
, char **argv
)
259 dns_config_t
*config
;
261 config
= dns_configuration_copy();
262 if (config
!= NULL
) {
263 dns_configuration_free(config
);