]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_copy.c
configd-1061.80.3.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_copy.c
1 /*
2 * Copyright (c) 2004, 2006, 2008-2013, 2015-2017, 2019 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 #include <xpc/xpc.h>
37
38 #ifndef SC_LOG_HANDLE
39 #include <os/log.h>
40 #define my_log(__level, __format, ...) os_log(OS_LOG_DEFAULT, __format, ## __VA_ARGS__)
41 #endif // SC_LOG_HANDLE
42
43 #include "libSystemConfiguration_client.h"
44 #include "dnsinfo.h"
45 #include "dnsinfo_private.h"
46 #include "dnsinfo_internal.h"
47
48
49 const char *
50 dns_configuration_notify_key()
51 {
52 const char *key;
53
54 key = "com.apple.system.SystemConfiguration.dns_configuration";
55 return key;
56 }
57
58
59 #pragma mark -
60 #pragma mark DNS configuration [dnsinfo] client support
61
62
63 // Note: protected by __dns_configuration_queue()
64 static int dnsinfo_active = 0;
65 static libSC_info_client_t *dnsinfo_client = NULL;
66
67
68 static dispatch_queue_t
69 __dns_configuration_queue()
70 {
71 static dispatch_once_t once;
72 static dispatch_queue_t q;
73
74 dispatch_once(&once, ^{
75 q = dispatch_queue_create(DNSINFO_SERVICE_NAME, NULL);
76 });
77
78 return q;
79 }
80
81
82 dns_config_t *
83 dns_configuration_copy()
84 {
85 dns_config_t *dns_config = NULL;
86 _dns_config_buf_t *dns_config_buf = NULL;
87 static const char *proc_name = NULL;
88 xpc_object_t reqdict;
89 xpc_object_t reply;
90
91 if (!libSC_info_available()) {
92 os_log(OS_LOG_DEFAULT, "*** DNS configuration requested between fork() and exec()");
93 return NULL;
94 }
95
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;
100
101 dispatch_once(&once, ^{
102 #if DEBUG
103 const char *name;
104
105 // get [XPC] service name
106 name = getenv(service_name);
107 if (name != NULL) {
108 service_name = strdup(name);
109 }
110 #endif // DEBUG
111
112 // get process name
113 proc_name = getprogname();
114 });
115
116 dnsinfo_client =
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) {
121 --dnsinfo_active;
122 }
123 }
124 });
125
126 if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
127 // if DNS configuration server not available
128 return NULL;
129 }
130
131 // create message
132 reqdict = xpc_dictionary_create(NULL, NULL, 0);
133
134 // set process name
135 if (proc_name != NULL) {
136 xpc_dictionary_set_string(reqdict, DNSINFO_PROC_NAME, proc_name);
137 }
138
139 // set request
140 xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_COPY);
141
142 // send request to the DNS configuration server
143 reply = libSC_send_message_with_reply_sync(dnsinfo_client, reqdict);
144 xpc_release(reqdict);
145
146 if (reply != NULL) {
147 const void *dataRef;
148 size_t dataLen = 0;
149
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);
154 }
155
156 xpc_release(reply);
157 }
158
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);
164 }
165 }
166
167 return dns_config;
168 }
169
170
171 void
172 dns_configuration_free(dns_config_t *config)
173 {
174 if (config == NULL) {
175 return; // ASSERT
176 }
177
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;
183 }
184 });
185
186 free((void *)config);
187 return;
188 }
189
190
191 void
192 _dns_configuration_ack(dns_config_t *config, const char *bundle_id)
193 {
194 #pragma unused(bundle_id)
195 xpc_object_t reqdict;
196
197 if (config == NULL) {
198 return; // ASSERT
199 }
200
201 if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
202 // if DNS configuration server not available
203 return;
204 }
205
206 dispatch_sync(__dns_configuration_queue(), ^{
207 dnsinfo_active++; // keep connection active (for the life of the process)
208 });
209
210 // create message
211 reqdict = xpc_dictionary_create(NULL, NULL, 0);
212
213 // set request
214 xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_ACKNOWLEDGE);
215
216 // set generation
217 xpc_dictionary_set_uint64(reqdict, DNSINFO_GENERATION, config->generation);
218
219 // send acknowledgement to the DNS configuration server
220 xpc_connection_send_message(dnsinfo_client->connection, reqdict);
221
222 xpc_release(reqdict);
223 return;
224 }
225
226 #ifdef MAIN
227
228 int
229 main(int argc, char **argv)
230 {
231 dns_config_t *config;
232
233 config = dns_configuration_copy();
234 if (config != NULL) {
235 dns_configuration_free(config);
236 }
237
238 exit(0);
239 }
240
241 #endif