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()
82 dns_config_t
*config
= NULL
;
83 static const char *proc_name
= NULL
;
87 dispatch_sync(__dns_configuration_queue(), ^{
88 if ((dnsinfo_active
++ == 0) || (dnsinfo_client
== NULL
)) {
89 static dispatch_once_t once
;
90 static const char *service_name
= DNSINFO_SERVICE_NAME
;
92 dispatch_once(&once
, ^{
95 // get [XPC] service name
96 name
= getenv(service_name
);
97 if ((name
!= NULL
) && (issetugid() == 0)) {
98 service_name
= strdup(name
);
102 proc_name
= getprogname();
106 libSC_info_client_create(__dns_configuration_queue(), // dispatch queue
107 service_name
, // XPC service name
108 "DNS configuration"); // service description
109 if (dnsinfo_client
== NULL
) {
115 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
116 // if DNS configuration server not available
121 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
124 if (proc_name
!= NULL
) {
125 xpc_dictionary_set_string(reqdict
, DNSINFO_PROC_NAME
, proc_name
);
129 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_COPY
);
131 // send request to the DNS configuration server
132 reply
= libSC_send_message_with_reply_sync(dnsinfo_client
, reqdict
);
133 xpc_release(reqdict
);
139 dataRef
= xpc_dictionary_get_data(reply
, DNSINFO_CONFIGURATION
, &dataLen
);
140 if ((dataRef
!= NULL
) &&
141 ((dataLen
>= sizeof(_dns_config_buf_t
)) && (dataLen
<= DNS_CONFIG_BUF_MAX
))) {
142 _dns_config_buf_t
*config
= (_dns_config_buf_t
*)(void *)dataRef
;
143 uint32_t n_padding
= ntohl(config
->n_padding
);
145 if (n_padding
<= (DNS_CONFIG_BUF_MAX
- dataLen
)) {
148 len
= dataLen
+ n_padding
;
150 bcopy((void *)dataRef
, buf
, dataLen
);
151 bzero(&buf
[dataLen
], n_padding
);
159 /* ALIGN: cast okay since _dns_config_buf_t is int aligned */
160 config
= _dns_configuration_expand_config((_dns_config_buf_t
*)(void *)buf
);
161 if (config
== NULL
) {
171 dns_configuration_free(dns_config_t
*config
)
173 if (config
== NULL
) {
177 dispatch_sync(__dns_configuration_queue(), ^{
178 if (--dnsinfo_active
== 0) {
179 // if last reference, drop connection
180 libSC_info_client_release(dnsinfo_client
);
181 dnsinfo_client
= NULL
;
185 free((void *)config
);
191 _dns_configuration_ack(dns_config_t
*config
, const char *bundle_id
)
193 xpc_object_t reqdict
;
195 if (config
== NULL
) {
199 if ((dnsinfo_client
== NULL
) || !dnsinfo_client
->active
) {
200 // if DNS configuration server not available
204 dispatch_sync(__dns_configuration_queue(), ^{
205 dnsinfo_active
++; // keep connection active (for the life of the process)
209 reqdict
= xpc_dictionary_create(NULL
, NULL
, 0);
212 xpc_dictionary_set_int64(reqdict
, DNSINFO_REQUEST
, DNSINFO_REQUEST_ACKNOWLEDGE
);
215 xpc_dictionary_set_uint64(reqdict
, DNSINFO_GENERATION
, config
->generation
);
217 // send acknowledgement to the DNS configuration server
218 xpc_connection_send_message(dnsinfo_client
->connection
, reqdict
);
220 xpc_release(reqdict
);
227 main(int argc
, char **argv
)
229 dns_config_t
*config
;
231 config
= dns_configuration_copy();
232 if (config
!= NULL
) {
233 dns_configuration_free(config
);