2 * Copyright (c) 2004-2008, 2016-2020 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * Modification History
27 * May 13, 2004 Allan Nathanson <ajn@apple.com>
32 #include <CoreFoundation/CoreFoundation.h>
33 #include <CoreFoundation/CFRuntime.h>
34 #include "SCNetworkConfigurationInternal.h"
39 static CFStringRef
__SCNetworkProtocolCopyDescription (CFTypeRef cf
);
40 static void __SCNetworkProtocolDeallocate (CFTypeRef cf
);
41 static Boolean
__SCNetworkProtocolEqual (CFTypeRef cf1
, CFTypeRef cf2
);
42 static CFHashCode
__SCNetworkProtocolHash (CFTypeRef cf
);
45 const CFStringRef kSCNetworkProtocolTypeDNS
= CFSTR("DNS");
46 const CFStringRef kSCNetworkProtocolTypeIPv4
= CFSTR("IPv4");
47 const CFStringRef kSCNetworkProtocolTypeIPv6
= CFSTR("IPv6");
48 const CFStringRef kSCNetworkProtocolTypeProxies
= CFSTR("Proxies");
50 const CFStringRef kSCNetworkProtocolTypeSMB
= CFSTR("SMB");
51 #endif // !TARGET_OS_IPHONE
54 static CFTypeID __kSCNetworkProtocolTypeID
= _kCFRuntimeNotATypeID
;
57 static const CFRuntimeClass __SCNetworkProtocolClass
= {
59 "SCNetworkProtocol", // className
62 __SCNetworkProtocolDeallocate
, // dealloc
63 __SCNetworkProtocolEqual
, // equal
64 __SCNetworkProtocolHash
, // hash
65 NULL
, // copyFormattingDesc
66 __SCNetworkProtocolCopyDescription
// copyDebugDesc
70 static pthread_once_t initialized
= PTHREAD_ONCE_INIT
;
74 __SCNetworkProtocolCopyDescription(CFTypeRef cf
)
76 CFAllocatorRef allocator
= CFGetAllocator(cf
);
77 CFMutableStringRef result
;
78 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)cf
;
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("}"));
94 __SCNetworkProtocolDeallocate(CFTypeRef cf
)
96 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)cf
;
98 /* release resources */
99 CFRelease(protocolPrivate
->entityID
);
100 CFRelease(protocolPrivate
->service
);
107 __SCNetworkProtocolEqual(CFTypeRef cf1
, CFTypeRef cf2
)
109 SCNetworkProtocolPrivateRef p1
= (SCNetworkProtocolPrivateRef
)cf1
;
110 SCNetworkProtocolPrivateRef p2
= (SCNetworkProtocolPrivateRef
)cf2
;
115 if (!CFEqual(p1
->entityID
, p2
->entityID
))
116 return FALSE
; // if not the same protocol type
118 if (p1
->service
== p2
->service
)
119 return TRUE
; // if both point to the same service
121 if ((p1
->service
!= NULL
) && (p2
->service
!= NULL
) && CFEqual(p1
->service
, p2
->service
))
122 return TRUE
; // if both effectively point to the same service
129 __SCNetworkProtocolHash(CFTypeRef cf
)
131 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)cf
;
133 return CFHash(protocolPrivate
->entityID
);
138 __SCNetworkProtocolInitialize(void)
140 __kSCNetworkProtocolTypeID
= _CFRuntimeRegisterClass(&__SCNetworkProtocolClass
);
145 __private_extern__ SCNetworkProtocolPrivateRef
146 __SCNetworkProtocolCreatePrivate(CFAllocatorRef allocator
,
147 CFStringRef entityID
,
148 SCNetworkServiceRef service
)
150 SCNetworkProtocolPrivateRef protocolPrivate
;
153 /* initialize runtime */
154 pthread_once(&initialized
, __SCNetworkProtocolInitialize
);
156 /* allocate target */
157 size
= sizeof(SCNetworkProtocolPrivate
) - sizeof(CFRuntimeBase
);
158 protocolPrivate
= (SCNetworkProtocolPrivateRef
)_CFRuntimeCreateInstance(allocator
,
159 __kSCNetworkProtocolTypeID
,
162 if (protocolPrivate
== NULL
) {
166 /* initialize non-zero/NULL members */
167 protocolPrivate
->entityID
= CFStringCreateCopy(NULL
, entityID
);
168 protocolPrivate
->service
= CFRetain(service
);
170 return protocolPrivate
;
174 __private_extern__ Boolean
175 __SCNetworkProtocolIsValidType(CFStringRef protocolType
)
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
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
194 if (CFStringFindWithOptions(protocolType
,
196 CFRangeMake(0, CFStringGetLength(protocolType
)),
199 // if user-defined protocol type (e.g. com.apple.myProtocol)
208 copyProtocolConfigurationPath(SCNetworkProtocolPrivateRef protocolPrivate
)
211 SCNetworkServicePrivateRef servicePrivate
;
213 servicePrivate
= (SCNetworkServicePrivateRef
)protocolPrivate
->service
;
214 path
= SCPreferencesPathKeyCreateNetworkServiceEntity(NULL
, // allocator
215 servicePrivate
->serviceID
, // service
216 protocolPrivate
->entityID
); // entity
222 #pragma mark SCNetworkProtocol APIs
226 _SCNetworkProtocolCompare(const void *val1
, const void *val2
, void *context
)
228 #pragma unused(context)
229 SCNetworkProtocolRef p1
= (SCNetworkProtocolRef
)val1
;
230 SCNetworkProtocolRef p2
= (SCNetworkProtocolRef
)val2
;
234 type1
= SCNetworkProtocolGetProtocolType(p1
);
235 type2
= SCNetworkProtocolGetProtocolType(p2
);
237 return CFStringCompare(type1
, type2
, 0);
242 SCNetworkProtocolGetTypeID()
244 pthread_once(&initialized
, __SCNetworkProtocolInitialize
); /* initialize runtime */
245 return __kSCNetworkProtocolTypeID
;
250 SCNetworkProtocolGetConfiguration(SCNetworkProtocolRef protocol
)
252 CFDictionaryRef config
;
254 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)protocol
;
255 SCNetworkServicePrivateRef servicePrivate
;
257 if (!isA_SCNetworkProtocol(protocol
)) {
258 _SCErrorSet(kSCStatusInvalidArgument
);
262 servicePrivate
= (SCNetworkServicePrivateRef
)protocolPrivate
->service
;
263 path
= copyProtocolConfigurationPath(protocolPrivate
);
264 config
= __SCNetworkConfigurationGetValue(servicePrivate
->prefs
, path
);
272 SCNetworkProtocolGetEnabled(SCNetworkProtocolRef protocol
)
276 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)protocol
;
277 SCNetworkServicePrivateRef servicePrivate
;
279 if (!isA_SCNetworkProtocol(protocol
)) {
280 _SCErrorSet(kSCStatusInvalidArgument
);
284 servicePrivate
= (SCNetworkServicePrivateRef
)protocolPrivate
->service
;
285 path
= copyProtocolConfigurationPath(protocolPrivate
);
286 enabled
= __getPrefsEnabled(servicePrivate
->prefs
, path
);
294 SCNetworkProtocolGetProtocolType(SCNetworkProtocolRef protocol
)
296 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)protocol
;
298 if (!isA_SCNetworkProtocol(protocol
)) {
299 _SCErrorSet(kSCStatusInvalidArgument
);
303 return protocolPrivate
->entityID
;
308 SCNetworkProtocolSetConfiguration(SCNetworkProtocolRef protocol
, CFDictionaryRef config
)
312 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)protocol
;
313 SCNetworkServiceRef service
;
314 SCNetworkServicePrivateRef servicePrivate
;
316 if (!isA_SCNetworkProtocol(protocol
)) {
317 _SCErrorSet(kSCStatusInvalidArgument
);
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
,
327 _SC_crash_once("SCNetworkProtocolSetConfiguration() w/removed service", NULL
, NULL
);
328 _SCErrorSet(kSCStatusInvalidArgument
);
332 path
= copyProtocolConfigurationPath(protocolPrivate
);
333 ok
= __SCNetworkConfigurationSetValue(servicePrivate
->prefs
, path
, config
, TRUE
);
337 SC_log(LOG_DEBUG
, "SCNetworkProtocolSetConfiguration(): %@ --> %@",
339 config
!= NULL
? config
: (CFDictionaryRef
)CFSTR("NULL"));
347 SCNetworkProtocolSetEnabled(SCNetworkProtocolRef protocol
, Boolean enabled
)
351 SCNetworkProtocolPrivateRef protocolPrivate
= (SCNetworkProtocolPrivateRef
)protocol
;
352 SCNetworkServiceRef service
;
353 SCNetworkServicePrivateRef servicePrivate
;
355 if (!isA_SCNetworkProtocol(protocol
)) {
356 _SCErrorSet(kSCStatusInvalidArgument
);
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
,
366 _SC_crash_once("SCNetworkProtocolSetEnabled() w/removed service", NULL
, NULL
);
367 _SCErrorSet(kSCStatusInvalidArgument
);
371 path
= copyProtocolConfigurationPath(protocolPrivate
);
372 ok
= __setPrefsEnabled(servicePrivate
->prefs
, path
, enabled
);
376 SC_log(LOG_DEBUG
, "SCNetworkProtocolSetEnabled(): %@ -> %s",
378 enabled
? "Enabled" : "Disabled");