this repo has no description
1/*
2 * Copyright (c) 2004-2008, 2016-2018 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 * May 13, 2004 Allan Nathanson <ajn@apple.com>
28 * - initial revision
29 */
30
31
32#include <CoreFoundation/CoreFoundation.h>
33#include <CoreFoundation/CFRuntime.h>
34#include "SCNetworkConfigurationInternal.h"
35
36#include <pthread.h>
37
38
39static CFStringRef __SCNetworkProtocolCopyDescription (CFTypeRef cf);
40static void __SCNetworkProtocolDeallocate (CFTypeRef cf);
41static Boolean __SCNetworkProtocolEqual (CFTypeRef cf1, CFTypeRef cf2);
42static CFHashCode __SCNetworkProtocolHash (CFTypeRef cf);
43
44
45const CFStringRef kSCNetworkProtocolTypeDNS = CFSTR("DNS");
46const CFStringRef kSCNetworkProtocolTypeIPv4 = CFSTR("IPv4");
47const CFStringRef kSCNetworkProtocolTypeIPv6 = CFSTR("IPv6");
48const CFStringRef kSCNetworkProtocolTypeProxies = CFSTR("Proxies");
49#if !TARGET_OS_IPHONE
50const CFStringRef kSCNetworkProtocolTypeSMB = CFSTR("SMB");
51#endif // !TARGET_OS_IPHONE
52
53
54static CFTypeID __kSCNetworkProtocolTypeID = _kCFRuntimeNotATypeID;
55
56
57static const CFRuntimeClass __SCNetworkProtocolClass = {
58 0, // version
59 "SCNetworkProtocol", // className
60 NULL, // init
61 NULL, // copy
62 __SCNetworkProtocolDeallocate, // dealloc
63 __SCNetworkProtocolEqual, // equal
64 __SCNetworkProtocolHash, // hash
65 NULL, // copyFormattingDesc
66 __SCNetworkProtocolCopyDescription // copyDebugDesc
67};
68
69
70static pthread_once_t initialized = PTHREAD_ONCE_INIT;
71
72
73static CFStringRef
74__SCNetworkProtocolCopyDescription(CFTypeRef cf)
75{
76 CFAllocatorRef allocator = CFGetAllocator(cf);
77 CFMutableStringRef result;
78 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
79
80 result = CFStringCreateMutable(allocator, 0);
81 CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkProtocol %p [%p]> {"), cf, allocator);
82 CFStringAppendFormat(result, NULL, CFSTR("id = %@"), protocolPrivate->entityID);
83 CFStringAppendFormat(result, NULL, CFSTR(", service = %p"), protocolPrivate->service);
84 CFStringAppendFormat(result, NULL,
85 CFSTR(", prefs = %p"),
86 ((SCNetworkServicePrivateRef)protocolPrivate->service)->prefs);
87 CFStringAppendFormat(result, NULL, CFSTR("}"));
88
89 return result;
90}
91
92
93static void
94__SCNetworkProtocolDeallocate(CFTypeRef cf)
95{
96 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
97
98 /* release resources */
99 CFRelease(protocolPrivate->entityID);
100 CFRelease(protocolPrivate->service);
101
102 return;
103}
104
105
106static Boolean
107__SCNetworkProtocolEqual(CFTypeRef cf1, CFTypeRef cf2)
108{
109 SCNetworkProtocolPrivateRef p1 = (SCNetworkProtocolPrivateRef)cf1;
110 SCNetworkProtocolPrivateRef p2 = (SCNetworkProtocolPrivateRef)cf2;
111
112 if (p1 == p2)
113 return TRUE;
114
115 if (!CFEqual(p1->entityID, p2->entityID))
116 return FALSE; // if not the same protocol type
117
118 if (p1->service == p2->service)
119 return TRUE; // if both point to the same service
120
121 if ((p1->service != NULL) && (p2->service != NULL) && CFEqual(p1->service, p2->service))
122 return TRUE; // if both effectively point to the same service
123
124 return FALSE;
125}
126
127
128static CFHashCode
129__SCNetworkProtocolHash(CFTypeRef cf)
130{
131 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)cf;
132
133 return CFHash(protocolPrivate->entityID);
134}
135
136
137static void
138__SCNetworkProtocolInitialize(void)
139{
140 __kSCNetworkProtocolTypeID = _CFRuntimeRegisterClass(&__SCNetworkProtocolClass);
141 return;
142}
143
144
145__private_extern__ SCNetworkProtocolPrivateRef
146__SCNetworkProtocolCreatePrivate(CFAllocatorRef allocator,
147 CFStringRef entityID,
148 SCNetworkServiceRef service)
149{
150 SCNetworkProtocolPrivateRef protocolPrivate;
151 uint32_t size;
152
153 /* initialize runtime */
154 pthread_once(&initialized, __SCNetworkProtocolInitialize);
155
156 /* allocate target */
157 size = sizeof(SCNetworkProtocolPrivate) - sizeof(CFRuntimeBase);
158 protocolPrivate = (SCNetworkProtocolPrivateRef)_CFRuntimeCreateInstance(allocator,
159 __kSCNetworkProtocolTypeID,
160 size,
161 NULL);
162 if (protocolPrivate == NULL) {
163 return NULL;
164 }
165
166 /* initialize non-zero/NULL members */
167 protocolPrivate->entityID = CFStringCreateCopy(NULL, entityID);
168 protocolPrivate->service = CFRetain(service);
169
170 return protocolPrivate;
171}
172
173
174__private_extern__ Boolean
175__SCNetworkProtocolIsValidType(CFStringRef protocolType)
176{
177 static const CFStringRef *valid_types[] = {
178 &kSCNetworkProtocolTypeDNS,
179 &kSCNetworkProtocolTypeIPv4,
180 &kSCNetworkProtocolTypeIPv6,
181 &kSCNetworkProtocolTypeProxies,
182#if !TARGET_OS_IPHONE
183 &kSCNetworkProtocolTypeSMB,
184#endif // !TARGET_OS_IPHONE
185 };
186
187 for (size_t i = 0; i < sizeof(valid_types)/sizeof(valid_types[0]); i++) {
188 if (CFEqual(protocolType, *valid_types[i])) {
189 // if known/valid protocol type
190 return TRUE;
191 }
192 }
193
194 if (CFStringFindWithOptions(protocolType,
195 CFSTR("."),
196 CFRangeMake(0, CFStringGetLength(protocolType)),
197 0,
198 NULL)) {
199 // if user-defined protocol type (e.g. com.apple.myProtocol)
200 return TRUE;
201 }
202
203 return FALSE;
204}
205
206
207static CFStringRef
208copyProtocolConfigurationPath(SCNetworkProtocolPrivateRef protocolPrivate)
209{
210 CFStringRef path;
211 SCNetworkServicePrivateRef servicePrivate;
212
213 servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
214 path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator
215 servicePrivate->serviceID, // service
216 protocolPrivate->entityID); // entity
217 return path;
218}
219
220
221#pragma mark -
222#pragma mark SCNetworkProtocol APIs
223
224
225CFComparisonResult
226_SCNetworkProtocolCompare(const void *val1, const void *val2, void *context)
227{
228#pragma unused(context)
229 SCNetworkProtocolRef p1 = (SCNetworkProtocolRef)val1;
230 SCNetworkProtocolRef p2 = (SCNetworkProtocolRef)val2;
231 CFStringRef type1;
232 CFStringRef type2;
233
234 type1 = SCNetworkProtocolGetProtocolType(p1);
235 type2 = SCNetworkProtocolGetProtocolType(p2);
236
237 return CFStringCompare(type1, type2, 0);
238}
239
240
241CFTypeID
242SCNetworkProtocolGetTypeID()
243{
244 pthread_once(&initialized, __SCNetworkProtocolInitialize); /* initialize runtime */
245 return __kSCNetworkProtocolTypeID;
246}
247
248
249CFDictionaryRef
250SCNetworkProtocolGetConfiguration(SCNetworkProtocolRef protocol)
251{
252 CFDictionaryRef config;
253 CFStringRef path;
254 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
255 SCNetworkServicePrivateRef servicePrivate;
256
257 if (!isA_SCNetworkProtocol(protocol)) {
258 _SCErrorSet(kSCStatusInvalidArgument);
259 return NULL;
260 }
261
262 servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
263 path = copyProtocolConfigurationPath(protocolPrivate);
264 config = __getPrefsConfiguration(servicePrivate->prefs, path);
265 CFRelease(path);
266
267 return config;
268}
269
270
271Boolean
272SCNetworkProtocolGetEnabled(SCNetworkProtocolRef protocol)
273{
274 Boolean enabled;
275 CFStringRef path;
276 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
277 SCNetworkServicePrivateRef servicePrivate;
278
279 if (!isA_SCNetworkProtocol(protocol)) {
280 _SCErrorSet(kSCStatusInvalidArgument);
281 return FALSE;
282 }
283
284 servicePrivate = (SCNetworkServicePrivateRef)protocolPrivate->service;
285 path = copyProtocolConfigurationPath(protocolPrivate);
286 enabled = __getPrefsEnabled(servicePrivate->prefs, path);
287 CFRelease(path);
288
289 return enabled;
290}
291
292
293CFStringRef
294SCNetworkProtocolGetProtocolType(SCNetworkProtocolRef protocol)
295{
296 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
297
298 if (!isA_SCNetworkProtocol(protocol)) {
299 _SCErrorSet(kSCStatusInvalidArgument);
300 return NULL;
301 }
302
303 return protocolPrivate->entityID;
304}
305
306
307Boolean
308SCNetworkProtocolSetConfiguration(SCNetworkProtocolRef protocol, CFDictionaryRef config)
309{
310 Boolean ok;
311 CFStringRef path;
312 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
313 SCNetworkServiceRef service;
314 SCNetworkServicePrivateRef servicePrivate;
315
316 if (!isA_SCNetworkProtocol(protocol)) {
317 _SCErrorSet(kSCStatusInvalidArgument);
318 return FALSE;
319 }
320
321 service = protocolPrivate->service;
322 servicePrivate = (SCNetworkServicePrivateRef)service;
323 if (!__SCNetworkServiceExists(service)) {
324 SC_log(LOG_ERR, "SCNetworkProtocolSetConfiguration() w/removed service\n protocol = %@\n service = %@",
325 protocolPrivate->entityID,
326 servicePrivate);
327 _SC_crash_once("SCNetworkProtocolSetConfiguration() w/removed service", NULL, NULL);
328 _SCErrorSet(kSCStatusInvalidArgument);
329 return FALSE;
330 }
331
332 path = copyProtocolConfigurationPath(protocolPrivate);
333 ok = __setPrefsConfiguration(servicePrivate->prefs, path, config, TRUE);
334 CFRelease(path);
335
336 if (ok) {
337 SC_log(LOG_DEBUG, "SCNetworkProtocolSetConfiguration(): %@ --> %@",
338 protocol,
339 config != NULL ? config : (CFDictionaryRef)CFSTR("NULL"));
340 }
341
342 return ok;
343}
344
345
346Boolean
347SCNetworkProtocolSetEnabled(SCNetworkProtocolRef protocol, Boolean enabled)
348{
349 Boolean ok;
350 CFStringRef path;
351 SCNetworkProtocolPrivateRef protocolPrivate = (SCNetworkProtocolPrivateRef)protocol;
352 SCNetworkServiceRef service;
353 SCNetworkServicePrivateRef servicePrivate;
354
355 if (!isA_SCNetworkProtocol(protocol)) {
356 _SCErrorSet(kSCStatusInvalidArgument);
357 return FALSE;
358 }
359
360 service = protocolPrivate->service;
361 servicePrivate = (SCNetworkServicePrivateRef)service;
362 if (!__SCNetworkServiceExists(service)) {
363 SC_log(LOG_ERR, "SCNetworkProtocolSetEnabled() w/removed service\n protocol = %@\n service = %@",
364 protocolPrivate->entityID,
365 servicePrivate);
366 _SC_crash_once("SCNetworkProtocolSetEnabled() w/removed service", NULL, NULL);
367 _SCErrorSet(kSCStatusInvalidArgument);
368 return FALSE;
369 }
370
371 path = copyProtocolConfigurationPath(protocolPrivate);
372 ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled);
373 CFRelease(path);
374
375 if (ok) {
376 SC_log(LOG_DEBUG, "SCNetworkProtocolSetEnabled(): %@ -> %s",
377 protocol,
378 enabled ? "Enabled" : "Disabled");
379 }
380
381 return ok;
382}