]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_copy.c
configd-963.50.8.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_copy.c
1 /*
2 * Copyright (c) 2004, 2006, 2008-2013, 2015-2017 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * Modification History
26 *
27 * March 9, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <pthread.h>
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
39 #include <xpc/xpc.h>
40
41 #ifndef SC_LOG_HANDLE
42 #include <os/log.h>
43 #define my_log(__level, __format, ...) os_log(OS_LOG_DEFAULT, __format, ## __VA_ARGS__)
44 #endif // SC_LOG_HANDLE
45
46 #include "libSystemConfiguration_client.h"
47 #include "dnsinfo.h"
48 #include "dnsinfo_private.h"
49 #include "dnsinfo_internal.h"
50
51
52 const char *
53 dns_configuration_notify_key()
54 {
55 const char *key;
56
57 key = "com.apple.system.SystemConfiguration.dns_configuration";
58 return key;
59 }
60
61
62 #pragma mark -
63 #pragma mark DNS configuration [dnsinfo] client support
64
65
66 // Note: protected by __dns_configuration_queue()
67 static int dnsinfo_active = 0;
68 static libSC_info_client_t *dnsinfo_client = NULL;
69
70
71 #ifdef VERBOSE_ACTIVITY_LOGGING
72 static os_activity_t
73 __dns_configuration_activity()
74 {
75 static os_activity_t activity;
76 static dispatch_once_t once;
77
78 dispatch_once(&once, ^{
79 activity = os_activity_create("accessing DNS configuration",
80 OS_ACTIVITY_CURRENT,
81 OS_ACTIVITY_FLAG_DEFAULT);
82 });
83
84 return activity;
85 }
86 #endif // VERBOSE_ACTIVITY_LOGGING
87
88
89 static dispatch_queue_t
90 __dns_configuration_queue()
91 {
92 static dispatch_once_t once;
93 static dispatch_queue_t q;
94
95 dispatch_once(&once, ^{
96 q = dispatch_queue_create(DNSINFO_SERVICE_NAME, NULL);
97 });
98
99 return q;
100 }
101
102
103 dns_config_t *
104 dns_configuration_copy()
105 {
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;
110 xpc_object_t reply;
111
112 if (!libSC_info_available()) {
113 os_log(OS_LOG_DEFAULT, "*** DNS configuration requested between fork() and exec()");
114 return NULL;
115 }
116
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;
121
122 dispatch_once(&once, ^{
123 #if DEBUG
124 const char *name;
125
126 // get [XPC] service name
127 name = getenv(service_name);
128 if (name != NULL) {
129 service_name = strdup(name);
130 }
131 #endif // DEBUG
132
133 // get process name
134 proc_name = getprogname();
135 });
136
137 dnsinfo_client =
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) {
142 --dnsinfo_active;
143 }
144 }
145 });
146
147 if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
148 // if DNS configuration server not available
149 return NULL;
150 }
151
152 #ifdef VERBOSE_ACTIVITY_LOGGING
153 // scope DNS configuration activity
154 os_activity_scope(__dns_configuration_activity());
155 #endif // VERBOSE_ACTIVITY_LOGGING
156
157 // create message
158 reqdict = xpc_dictionary_create(NULL, NULL, 0);
159
160 // set process name
161 if (proc_name != NULL) {
162 xpc_dictionary_set_string(reqdict, DNSINFO_PROC_NAME, proc_name);
163 }
164
165 // set request
166 xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_COPY);
167
168 // send request to the DNS configuration server
169 reply = libSC_send_message_with_reply_sync(dnsinfo_client, reqdict);
170 xpc_release(reqdict);
171
172 if (reply != NULL) {
173 const void *dataRef;
174 size_t dataLen = 0;
175
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);
180 }
181
182 xpc_release(reply);
183 }
184
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);
190 }
191 }
192
193 return dns_config;
194 }
195
196
197 void
198 dns_configuration_free(dns_config_t *config)
199 {
200 if (config == NULL) {
201 return; // ASSERT
202 }
203
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;
209 }
210 });
211
212 free((void *)config);
213 return;
214 }
215
216
217 void
218 _dns_configuration_ack(dns_config_t *config, const char *bundle_id)
219 {
220 #pragma unused(bundle_id)
221 xpc_object_t reqdict;
222
223 if (config == NULL) {
224 return; // ASSERT
225 }
226
227 if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
228 // if DNS configuration server not available
229 return;
230 }
231
232 dispatch_sync(__dns_configuration_queue(), ^{
233 dnsinfo_active++; // keep connection active (for the life of the process)
234 });
235
236 // create message
237 reqdict = xpc_dictionary_create(NULL, NULL, 0);
238
239 // set request
240 xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_ACKNOWLEDGE);
241
242 // set generation
243 xpc_dictionary_set_uint64(reqdict, DNSINFO_GENERATION, config->generation);
244
245 // send acknowledgement to the DNS configuration server
246 xpc_connection_send_message(dnsinfo_client->connection, reqdict);
247
248 xpc_release(reqdict);
249 return;
250 }
251
252 #ifdef MAIN
253
254 int
255 main(int argc, char **argv)
256 {
257 dns_config_t *config;
258
259 config = dns_configuration_copy();
260 if (config != NULL) {
261 dns_configuration_free(config);
262 }
263
264 exit(0);
265 }
266
267 #endif