8071d4d27d850b7adf432e1f4923b91ebad9c1b5
[apple/configd.git] / config-agent-info / config_agent_info.c
1 /*
2 * Copyright (c) 2015, 2016 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 #include "config_agent_info.h"
26 #include "configAgentDefines.h"
27 #include "network_config_agent_info_priv.h"
28
29 #include <syslog.h>
30
31 static void
32 get_agent_uuid_if_OOB_data_required(xpc_object_t info, uuid_t uuid)
33 {
34 __block xpc_object_t agent_uuid = NULL;
35
36 if (xpc_get_type(info) == XPC_TYPE_ARRAY) {
37 xpc_array_apply(info, ^bool(size_t index, xpc_object_t value) {
38 if (value && xpc_get_type(value) == XPC_TYPE_DICTIONARY) {
39 agent_uuid = xpc_dictionary_get_value(info,
40 kConfigAgentOutOfBandDataUUID);
41 if (agent_uuid != NULL) {
42 return false;
43 }
44 }
45 return true;
46 });
47 } else if (xpc_get_type(info) == XPC_TYPE_DICTIONARY) {
48 agent_uuid = xpc_dictionary_get_value(info,
49 kConfigAgentOutOfBandDataUUID);
50 }
51
52 if (agent_uuid != NULL) {
53 const void *bytes = xpc_data_get_bytes_ptr(agent_uuid);
54 uuid_copy(uuid, bytes);
55 } else {
56 uuid_clear(uuid);
57 }
58 }
59
60 static boolean_t
61 is_a_config_agent(const struct netagent *agent)
62 {
63 const char *agentDomain;
64
65 if (agent == NULL) {
66 return false;
67 }
68
69 agentDomain = agent->netagent_domain;
70 if (agentDomain == NULL || strcmp(agentDomain, kConfigAgentDomain)) {
71 return false;
72 }
73
74 return true;
75 }
76
77 boolean_t
78 is_config_agent_type_dns(const struct netagent *agent)
79 {
80 if (!is_a_config_agent(agent)) {
81 return false;
82 }
83
84 const char *agentDesc = agent->netagent_type;
85 if (agentDesc == NULL || strcmp(agentDesc, kConfigAgentTypeDNS)) {
86 return false;
87 }
88
89 return true;
90 }
91
92 boolean_t
93 is_config_agent_type_proxy(const struct netagent *agent)
94 {
95 if (!is_a_config_agent(agent)) {
96 return false;
97 }
98
99 const char *agentDesc = agent->netagent_type;
100 if (agentDesc == NULL || strcmp(agentDesc, kConfigAgentTypeProxy)) {
101 return false;
102 }
103
104 return true;
105 }
106
107 static boolean_t
108 is_config_agent_type_dns_multicast(const struct netagent *agent)
109 {
110 if (strncmp(agent->netagent_desc, kConfigAgentTypeDNSMulticast, sizeof(kConfigAgentTypeDNSMulticast)-1) == 0) {
111 return true;
112 }
113
114 return false;
115 }
116
117 static boolean_t
118 is_config_agent_type_dns_private(const struct netagent *agent)
119 {
120 if (strncmp(agent->netagent_desc, kConfigAgentTypeDNSPrivate, sizeof(kConfigAgentTypeDNSPrivate)-1) == 0) {
121 return true;
122 }
123
124 return false;
125 }
126
127 xpc_object_t
128 config_agent_copy_dns_information(const struct netagent *agent)
129 {
130 xpc_object_t resolver = NULL;
131
132 if (!is_config_agent_type_dns(agent)) {
133 goto done;
134 }
135
136 if (agent->netagent_data_size <= 0 ) {
137 if (!is_config_agent_type_dns_private(agent) && !is_config_agent_type_dns_multicast(agent)) {
138 const char *agent_desc = (*(agent->netagent_desc) != '\0') ? agent->netagent_desc : kConfigAgentTypeDNS;
139 syslog(LOG_ERR, "Cannot parse config agent (%s). No data available", agent_desc);
140 }
141
142 goto done;
143 }
144
145 resolver = xpc_create_from_plist(agent->netagent_data, agent->netagent_data_size);
146
147 done:
148 return resolver;
149 }
150
151 xpc_object_t
152 config_agent_get_dns_nameservers(xpc_object_t resolver)
153 {
154 if (resolver == NULL) {
155 return NULL;
156 }
157
158 return xpc_dictionary_get_value(resolver, kConfigAgentDNSNameServers);
159 }
160
161 xpc_object_t
162 config_agent_get_dns_searchdomains(xpc_object_t resolver)
163 {
164 if (resolver == NULL) {
165 return NULL;
166 }
167
168 return xpc_dictionary_get_value(resolver, kConfigAgentDNSSearchDomains);
169 }
170
171 void
172 config_agent_free_dns_information(xpc_object_t resolver)
173 {
174 if (resolver == NULL) {
175 syslog(LOG_ERR, "Attempting to free invalid resolver");
176 return;
177 }
178
179 xpc_release(resolver);
180 }
181
182 xpc_object_t
183 config_agent_copy_proxy_information(const struct netagent *agent)
184 {
185 xpc_object_t info = NULL;
186
187 if (!is_config_agent_type_proxy(agent)) {
188 goto done;
189 }
190
191 if (agent->netagent_data_size <= 0 ) {
192 const char *agent_desc = (*(agent->netagent_desc) != '\0') ? agent->netagent_desc : kConfigAgentTypeProxy;
193 syslog(LOG_ERR, "Cannot parse config agent (%s). No data available", agent_desc);
194 goto done;
195 }
196
197 info = xpc_create_from_plist(agent->netagent_data, agent->netagent_data_size);
198
199 done:
200 return info;
201 }
202
203 xpc_object_t
204 config_agent_update_proxy_information(xpc_object_t proxyConfig)
205 {
206 if (proxyConfig == NULL) {
207 return NULL;
208 }
209
210 xpc_object_t newProxyConfig = NULL;
211 struct netagent agent;
212
213 get_agent_uuid_if_OOB_data_required(proxyConfig, agent.netagent_uuid);
214
215 if (uuid_is_null(agent.netagent_uuid) == 0) {
216 strlcpy(agent.netagent_type, kConfigAgentTypeProxy, sizeof(agent.netagent_type));
217
218 uint64_t length;
219 const void *buffer = _nwi_config_agent_copy_data(&agent, &length);
220 if (buffer != NULL && length > 0) {
221 newProxyConfig = xpc_create_from_plist(buffer, (size_t)length);
222 free((void *)buffer);
223 }
224 }
225
226 return newProxyConfig;
227 }
228
229 void
230 config_agent_free_proxy_information(xpc_object_t proxyConfig)
231 {
232 if (proxyConfig == NULL) {
233 syslog(LOG_ERR, "Attempting to free proxy configuration");
234 return;
235 }
236
237 xpc_release(proxyConfig);
238 }