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