]> git.saurik.com Git - apple/configd.git/blob - dnsinfo/dnsinfo_copy.c
configd-801.10.2.tar.gz
[apple/configd.git] / dnsinfo / dnsinfo_copy.c
1 /*
2 * Copyright (c) 2004, 2006, 2008-2013, 2015 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 <mach/mach.h>
35 #include <mach/mach_error.h>
36 #include <dispatch/dispatch.h>
37 #include <xpc/xpc.h>
38
39 #include "libSystemConfiguration_client.h"
40 #include "dnsinfo.h"
41 #include "dnsinfo_private.h"
42 #include "dnsinfo_internal.h"
43
44
45 const char *
46 dns_configuration_notify_key()
47 {
48 const char *key;
49
50 key = "com.apple.system.SystemConfiguration.dns_configuration";
51 return key;
52 }
53
54
55 #pragma mark -
56 #pragma mark DNS configuration [dnsinfo] client support
57
58
59 // Note: protected by __dns_configuration_queue()
60 static int dnsinfo_active = 0;
61 static libSC_info_client_t *dnsinfo_client = NULL;
62
63
64 static dispatch_queue_t
65 __dns_configuration_queue()
66 {
67 static dispatch_once_t once;
68 static dispatch_queue_t q;
69
70 dispatch_once(&once, ^{
71 q = dispatch_queue_create(DNSINFO_SERVICE_NAME, NULL);
72 });
73
74 return q;
75 }
76
77
78 dns_config_t *
79 dns_configuration_copy()
80 {
81 uint8_t *buf = NULL;
82 size_t bufLen;
83 dns_config_t *config = NULL;
84 static const char *proc_name = NULL;
85 xpc_object_t reqdict;
86 xpc_object_t reply;
87
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;
92
93 dispatch_once(&once, ^{
94 #if DEBUG
95 const char *name;
96
97 // get [XPC] service name
98 name = getenv(service_name);
99 if (name != NULL) {
100 service_name = strdup(name);
101 }
102 #endif // DEBUG
103
104 // get process name
105 proc_name = getprogname();
106 });
107
108 dnsinfo_client =
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) {
113 --dnsinfo_active;
114 }
115 }
116 });
117
118 if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
119 // if DNS configuration server not available
120 return NULL;
121 }
122
123 // create message
124 reqdict = xpc_dictionary_create(NULL, NULL, 0);
125
126 // set process name
127 if (proc_name != NULL) {
128 xpc_dictionary_set_string(reqdict, DNSINFO_PROC_NAME, proc_name);
129 }
130
131 // set request
132 xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_COPY);
133
134 // send request to the DNS configuration server
135 reply = libSC_send_message_with_reply_sync(dnsinfo_client, reqdict);
136 xpc_release(reqdict);
137
138 if (reply != NULL) {
139 const void *dataRef;
140 size_t dataLen = 0;
141
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;
146 size_t configLen;
147 uint32_t n_attribute = ntohl(config->n_attribute);
148 uint32_t n_padding = ntohl(config->n_padding);
149
150 /*
151 * Check that the size of the configuration header plus the size of the
152 * attribute data matches the size of the configuration buffer.
153 *
154 * If the sizes are different, something that should NEVER happen, CRASH!
155 */
156 configLen = sizeof(_dns_config_buf_t) + n_attribute;
157 assert(configLen == dataLen);
158
159 /*
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.
162 *
163 * If the requested padding size is too large, something that should NEVER
164 * happen, CRASH!
165 */
166 assert(n_padding <= (DNS_CONFIG_BUF_MAX - dataLen));
167
168 /*
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.
172 *
173 * If the length needed is too large, something that should NEVER happen, CRASH!
174 */
175 bufLen = dataLen + n_padding;
176 assert(bufLen <= DNS_CONFIG_BUF_MAX);
177
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);
183 }
184
185 xpc_release(reply);
186 }
187
188 if (buf != NULL) {
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) {
192 free(buf);
193 }
194 }
195
196 return config;
197 }
198
199
200 void
201 dns_configuration_free(dns_config_t *config)
202 {
203 if (config == NULL) {
204 return; // ASSERT
205 }
206
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;
212 }
213 });
214
215 free((void *)config);
216 return;
217 }
218
219
220 void
221 _dns_configuration_ack(dns_config_t *config, const char *bundle_id)
222 {
223 xpc_object_t reqdict;
224
225 if (config == NULL) {
226 return; // ASSERT
227 }
228
229 if ((dnsinfo_client == NULL) || !dnsinfo_client->active) {
230 // if DNS configuration server not available
231 return;
232 }
233
234 dispatch_sync(__dns_configuration_queue(), ^{
235 dnsinfo_active++; // keep connection active (for the life of the process)
236 });
237
238 // create message
239 reqdict = xpc_dictionary_create(NULL, NULL, 0);
240
241 // set request
242 xpc_dictionary_set_int64(reqdict, DNSINFO_REQUEST, DNSINFO_REQUEST_ACKNOWLEDGE);
243
244 // set generation
245 xpc_dictionary_set_uint64(reqdict, DNSINFO_GENERATION, config->generation);
246
247 // send acknowledgement to the DNS configuration server
248 xpc_connection_send_message(dnsinfo_client->connection, reqdict);
249
250 xpc_release(reqdict);
251 return;
252 }
253
254 #ifdef MAIN
255
256 int
257 main(int argc, char **argv)
258 {
259 dns_config_t *config;
260
261 config = dns_configuration_copy();
262 if (config != NULL) {
263 dns_configuration_free(config);
264 }
265
266 exit(0);
267 }
268
269 #endif