Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
75 kB · 2556 lines
C
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557/* * Copyright (c) 2004-2018 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */
/* * Modification History * * May 13, 2004 Allan Nathanson <ajn@apple.com> * - initial revision */
#include <CoreFoundation/CoreFoundation.h>#include <CoreFoundation/CFRuntime.h>#include "SCNetworkConfigurationInternal.h"#include "SCPreferencesInternal.h"
#include <pthread.h>
#define EXTERNAL_ID_DOMAIN_PREFIX "_"
static CFStringRef __SCNetworkServiceCopyDescription (CFTypeRef cf);static void __SCNetworkServiceDeallocate (CFTypeRef cf);static Boolean __SCNetworkServiceEqual (CFTypeRef cf1, CFTypeRef cf2);static CFHashCode __SCNetworkServiceHash (CFTypeRef cf);
static CFTypeID __kSCNetworkServiceTypeID = _kCFRuntimeNotATypeID;
static const CFRuntimeClass __SCNetworkServiceClass = { 0, // version "SCNetworkService", // className NULL, // init NULL, // copy __SCNetworkServiceDeallocate, // dealloc __SCNetworkServiceEqual, // equal __SCNetworkServiceHash, // hash NULL, // copyFormattingDesc __SCNetworkServiceCopyDescription // copyDebugDesc};
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
static CFStringRef__SCNetworkServiceCopyDescription(CFTypeRef cf){ CFAllocatorRef allocator = CFGetAllocator(cf); CFMutableStringRef result; SCNetworkServiceRef service = (SCNetworkServiceRef)cf; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
result = CFStringCreateMutable(allocator, 0); CFStringAppendFormat(result, NULL, CFSTR("<SCNetworkService %p [%p]> {"), service, allocator); CFStringAppendFormat(result, NULL, CFSTR("id = %@"), servicePrivate->serviceID); if (servicePrivate->prefs != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", prefs = %p"), servicePrivate->prefs); } else if (servicePrivate->store != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", store = %p"), servicePrivate->store); } if (servicePrivate->name != NULL) { CFStringAppendFormat(result, NULL, CFSTR(", name = %@"), servicePrivate->name); } if (!__SCNetworkServiceExists(service)) { CFStringAppendFormat(result, NULL, CFSTR(", REMOVED")); } CFStringAppendFormat(result, NULL, CFSTR("}"));
return result;}
static void__SCNetworkServiceDeallocate(CFTypeRef cf){ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf;
/* release resources */
CFRelease(servicePrivate->serviceID); if (servicePrivate->interface != NULL) CFRelease(servicePrivate->interface); if (servicePrivate->prefs != NULL) CFRelease(servicePrivate->prefs); if (servicePrivate->store != NULL) CFRelease(servicePrivate->store); if (servicePrivate->name != NULL) CFRelease(servicePrivate->name); if (servicePrivate->externalIDs != NULL) CFRelease(servicePrivate->externalIDs);
return;}
static Boolean__SCNetworkServiceEqual(CFTypeRef cf1, CFTypeRef cf2){ SCNetworkServicePrivateRef s1 = (SCNetworkServicePrivateRef)cf1; SCNetworkServicePrivateRef s2 = (SCNetworkServicePrivateRef)cf2;
if (s1 == s2) return TRUE;
if (s1->prefs != s2->prefs) return FALSE; // if not the same prefs
if (!CFEqual(s1->serviceID, s2->serviceID)) return FALSE; // if not the same service identifier
return TRUE;}
static CFHashCode__SCNetworkServiceHash(CFTypeRef cf){ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)cf;
return CFHash(servicePrivate->serviceID);}
static void__SCNetworkServiceInitialize(void){ __kSCNetworkServiceTypeID = _CFRuntimeRegisterClass(&__SCNetworkServiceClass); return;}
__private_extern__ SCNetworkServicePrivateRef__SCNetworkServiceCreatePrivate(CFAllocatorRef allocator, SCPreferencesRef prefs, CFStringRef serviceID, SCNetworkInterfaceRef interface){ SCNetworkServicePrivateRef servicePrivate; uint32_t size;
/* initialize runtime */ pthread_once(&initialized, __SCNetworkServiceInitialize);
/* allocate target */ size = sizeof(SCNetworkServicePrivate) - sizeof(CFRuntimeBase); servicePrivate = (SCNetworkServicePrivateRef)_CFRuntimeCreateInstance(allocator, __kSCNetworkServiceTypeID, size, NULL); if (servicePrivate == NULL) { return NULL; }
/* initialize non-zero/NULL members */ servicePrivate->prefs = (prefs != NULL) ? CFRetain(prefs): NULL; servicePrivate->serviceID = CFStringCreateCopy(NULL, serviceID); servicePrivate->interface = (interface != NULL) ? CFRetain(interface) : NULL;
return servicePrivate;}
#pragma mark -#pragma mark Service ordering
CFComparisonResult_SCNetworkServiceCompare(const void *val1, const void *val2, void *context){ CFStringRef id1; CFStringRef id2; CFArrayRef order = (CFArrayRef)context; SCNetworkServiceRef s1 = (SCNetworkServiceRef)val1; SCNetworkServiceRef s2 = (SCNetworkServiceRef)val2;
id1 = SCNetworkServiceGetServiceID(s1); id2 = SCNetworkServiceGetServiceID(s2);
if (order != NULL) { CFIndex o1; CFIndex o2; CFRange range;
range = CFRangeMake(0, CFArrayGetCount(order)); o1 = CFArrayGetFirstIndexOfValue(order, range, id1); o2 = CFArrayGetFirstIndexOfValue(order, range, id2);
if (o1 > o2) { return (o2 != kCFNotFound) ? kCFCompareGreaterThan : kCFCompareLessThan; } else if (o1 < o2) { return (o1 != kCFNotFound) ? kCFCompareLessThan : kCFCompareGreaterThan; } }
return CFStringCompare(id1, id2, 0);}
#pragma mark -#pragma mark SCNetworkService APIs
#define N_QUICK 64
__private_extern__ CFArrayRef /* of SCNetworkServiceRef's */__SCNetworkServiceCopyAllEnabled(SCPreferencesRef prefs){ CFMutableArrayRef array = NULL; CFIndex i_sets; CFIndex n_sets; CFArrayRef sets;
sets = SCNetworkSetCopyAll(prefs); if (sets == NULL) { return NULL; }
n_sets = CFArrayGetCount(sets); for (i_sets = 0; i_sets < n_sets; i_sets++) { CFIndex i_services; CFIndex n_services; CFArrayRef services; SCNetworkSetRef set;
set = CFArrayGetValueAtIndex(sets, i_sets); services = SCNetworkSetCopyServices(set); if (services == NULL) { continue; }
n_services = CFArrayGetCount(services); for (i_services = 0; i_services < n_services; i_services++) { SCNetworkServiceRef service;
service = CFArrayGetValueAtIndex(services, i_services); if (!SCNetworkServiceGetEnabled(service)) { // if not enabled continue; }
if ((array == NULL) || !CFArrayContainsValue(array, CFRangeMake(0, CFArrayGetCount(array)), service)) { if (array == NULL) { array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); } CFArrayAppendValue(array, service); } } CFRelease(services); } CFRelease(sets);
return array;}
__private_extern__ Boolean__SCNetworkServiceExistsForInterface(CFArrayRef services, SCNetworkInterfaceRef interface){ CFIndex i; CFIndex n;
n = isA_CFArray(services) ? CFArrayGetCount(services) : 0; for (i = 0; i < n; i++) { SCNetworkServiceRef service; SCNetworkInterfaceRef service_interface;
service = CFArrayGetValueAtIndex(services, i);
service_interface = SCNetworkServiceGetInterface(service); while (service_interface != NULL) { if (CFEqual(interface, service_interface)) { return TRUE; }
service_interface = SCNetworkInterfaceGetInterface(service_interface); } }
return FALSE;}
static voidmergeDict(const void *key, const void *value, void *context){ CFMutableDictionaryRef newDict = (CFMutableDictionaryRef)context;
CFDictionarySetValue(newDict, key, value); return;}
static CF_RETURNS_RETAINED CFDictionaryRef_protocolTemplate(SCNetworkServiceRef service, CFStringRef protocolType){ SCNetworkInterfaceRef interface; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; CFDictionaryRef template = NULL;
interface = servicePrivate->interface; if (interface != NULL) { SCNetworkInterfaceRef childInterface; CFStringRef childInterfaceType = NULL; CFStringRef interfaceType;
// get the template interfaceType = SCNetworkInterfaceGetInterfaceType(servicePrivate->interface); childInterface = SCNetworkInterfaceGetInterface(servicePrivate->interface); if (childInterface != NULL) { childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); }
template = __copyProtocolTemplate(interfaceType, childInterfaceType, protocolType); if (template != NULL) { CFDictionaryRef overrides;
// move to the interface at the lowest layer while (childInterface != NULL) { interface = childInterface; childInterface = SCNetworkInterfaceGetInterface(interface); }
overrides = __SCNetworkInterfaceGetTemplateOverrides(interface, protocolType); if (isA_CFDictionary(overrides)) { CFMutableDictionaryRef newTemplate;
newTemplate = CFDictionaryCreateMutableCopy(NULL, 0, template); CFDictionaryApplyFunction(overrides, mergeDict, newTemplate); CFRelease(template); template = newTemplate; } } }
if (template == NULL) { template = CFDictionaryCreate(NULL, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); }
return template;}
BooleanSCNetworkServiceAddProtocolType(SCNetworkServiceRef service, CFStringRef protocolType){ CFDictionaryRef entity; Boolean newEnabled; CFDictionaryRef newEntity = NULL; Boolean ok = FALSE; CFStringRef path; SCNetworkProtocolRef protocol = NULL; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkProtocolIsValidType(protocolType)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceAddProtocolType() w/removed service\n service = %@\n protocol = %@", service, protocolType); _SC_crash_once("SCNetworkServiceAddProtocolType() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service protocolType); // entity
entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); if (entity != NULL) { // if "protocol" already exists _SCErrorSet(kSCStatusKeyExists); goto done; }
newEntity = CFDictionaryCreate(NULL, NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity); CFRelease(newEntity); newEntity = NULL; if (!ok) { goto done; }
protocol = SCNetworkServiceCopyProtocol(service, protocolType); assert(protocol != NULL);
newEntity = _protocolTemplate(service, protocolType); assert(newEntity != NULL); ok = SCNetworkProtocolSetConfiguration(protocol, newEntity); if (!ok) { // could not set default configuration goto done; }
newEnabled = !CFDictionaryContainsKey(newEntity, kSCResvInactive); ok = SCNetworkProtocolSetEnabled(protocol, newEnabled); if (!ok) { // could not enable/disable protocol goto done; }
done :
if (newEntity != NULL) CFRelease(newEntity); if (protocol != NULL) CFRelease(protocol);
if (ok) { SC_log(LOG_DEBUG, "SCNetworkServiceAddProtocolType(): %@, %@", service, protocolType); }
CFRelease(path); return ok;}
CFArrayRef /* of SCNetworkServiceRef's */SCNetworkServiceCopyAll(SCPreferencesRef prefs){ CFMutableArrayRef array; CFIndex n; CFStringRef path; CFDictionaryRef services;
path = SCPreferencesPathKeyCreateNetworkServices(NULL); services = SCPreferencesPathGetValue(prefs, path); CFRelease(path);
if ((services != NULL) && !isA_CFDictionary(services)) { return NULL; }
array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
n = (services != NULL) ? CFDictionaryGetCount(services) : 0; if (n > 0) { CFIndex i; const void * keys_q[N_QUICK]; const void ** keys = keys_q; const void * vals_q[N_QUICK]; const void ** vals = vals_q;
if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0); } CFDictionaryGetKeysAndValues(services, keys, vals); for (i = 0; i < n; i++) { CFDictionaryRef entity; SCNetworkServicePrivateRef servicePrivate;
if (!isA_CFDictionary(vals[i])) { SC_log(LOG_INFO, "error w/service \"%@\"", keys[i]); continue; }
entity = CFDictionaryGetValue(vals[i], kSCEntNetInterface); if (!isA_CFDictionary(entity)) { // if no "interface" SC_log(LOG_INFO, "no \"%@\" entity for service \"%@\"", kSCEntNetInterface, keys[i]); continue; }
if (__SCNetworkInterfaceEntityIsPPTP(entity)) { SC_log(LOG_INFO, "PPTP services are no longer supported"); continue; }
servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, keys[i], NULL); assert(servicePrivate != NULL); CFArrayAppendValue(array, (SCNetworkServiceRef)servicePrivate); CFRelease(servicePrivate); } if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, vals); } }
return array;}
__private_extern__CFArrayRef /* of SCNetworkInterfaceRef's */__SCNetworkServiceCopyAllInterfaces(SCPreferencesRef prefs){ CFMutableArrayRef interfaces = NULL; CFArrayRef services = NULL; CFIndex servicesCount = 0; SCNetworkServiceRef service = NULL; SCNetworkInterfaceRef interface = NULL;
services = SCNetworkServiceCopyAll(prefs); if (services == NULL) { goto done; }
servicesCount = CFArrayGetCount(services); if (servicesCount == 0) { goto done; }
interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
for (CFIndex idx = 0; idx < servicesCount; idx++) { service = CFArrayGetValueAtIndex(services, idx); interface = SCNetworkServiceGetInterface(service);
if (isA_SCNetworkInterface(interface) == NULL) { continue; } CFArrayAppendValue(interfaces, interface); }
if (CFArrayGetCount(interfaces) == 0) { // Do not return an empty array CFRelease(interfaces); interfaces = NULL; }
done:
if (services != NULL) { CFRelease(services); } return interfaces;}
/* * build a list of all of a services entity types that are associated * with the services interface. The list will include : * * - entity types associated with the interface type (Ethernet, FireWire, PPP, ...) * - entity types associated with the interface sub-type (PPPSerial, PPPoE, L2TP, PPTP, ...) * - entity types associated with the hardware device (Ethernet, AirPort, FireWire, Modem, ...) */static CFSetRef_copyInterfaceEntityTypes(CFDictionaryRef protocols){ CFDictionaryRef interface; CFMutableSetRef interface_entity_types;
interface_entity_types = CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks);
interface = CFDictionaryGetValue(protocols, kSCEntNetInterface); if (isA_CFDictionary(interface)) { CFStringRef entities[] = { kSCPropNetInterfaceType, kSCPropNetInterfaceSubType, kSCPropNetInterfaceHardware };
// include the "Interface" entity itself CFSetAddValue(interface_entity_types, kSCEntNetInterface);
// include the entities associated with the interface for (size_t i = 0; i < sizeof(entities)/sizeof(entities[0]); i++) { CFStringRef entity;
entity = CFDictionaryGetValue(interface, entities[i]); if (isA_CFString(entity)) { CFSetAddValue(interface_entity_types, entity); } }
/* * and, because we've found some misguided network preference code * developers leaving [PPP] entity dictionaries around even though * they are unused and/or unneeded... */ CFSetAddValue(interface_entity_types, kSCEntNetPPP); }
return interface_entity_types;}
SCNetworkServiceRefSCNetworkServiceCopy(SCPreferencesRef prefs, CFStringRef serviceID){ CFDictionaryRef entity; CFStringRef path; SCNetworkServicePrivateRef servicePrivate;
if (!isA_CFString(serviceID)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator serviceID, // service kSCEntNetInterface); // entity entity = SCPreferencesPathGetValue(prefs, path); CFRelease(path);
if (!isA_CFDictionary(entity)) { // a "service" must have an "interface" _SCErrorSet(kSCStatusNoKey); return NULL; }
if (__SCNetworkInterfaceEntityIsPPTP(entity)) { SC_log(LOG_INFO, "PPTP services are no longer supported"); _SCErrorSet(kSCStatusNoKey); return NULL; }
servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, serviceID, NULL); return (SCNetworkServiceRef)servicePrivate;}
SCNetworkServiceRef_SCNetworkServiceCopyActive(SCDynamicStoreRef store, CFStringRef serviceID){ SCNetworkServicePrivateRef servicePrivate;
if (!isA_CFString(serviceID)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
servicePrivate = __SCNetworkServiceCreatePrivate(NULL, NULL, serviceID, NULL); assert(servicePrivate != NULL); if (store != NULL) { servicePrivate->store = CFRetain(store); } return (SCNetworkServiceRef)servicePrivate;}
SCNetworkProtocolRefSCNetworkServiceCopyProtocol(SCNetworkServiceRef service, CFStringRef protocolType){ CFSetRef non_protocol_entities; CFStringRef path; CFDictionaryRef protocols; SCNetworkProtocolPrivateRef protocolPrivate = NULL; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
if (!isA_CFString(protocolType)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path); CFRelease(path);
if (!isA_CFDictionary(protocols)) { // if corrupt prefs _SCErrorSet(kSCStatusFailed); return NULL; }
non_protocol_entities = _copyInterfaceEntityTypes(protocols); if (CFSetContainsValue(non_protocol_entities, protocolType)) { // if the "protocolType" matches an interface entity type _SCErrorSet(kSCStatusInvalidArgument); goto done; }
if (!CFDictionaryContainsKey(protocols, protocolType)) { // if the "protocolType" entity does not exist _SCErrorSet(kSCStatusNoKey); goto done; }
protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, protocolType, service);
done :
CFRelease(non_protocol_entities);
return (SCNetworkProtocolRef)protocolPrivate;}
CFArrayRef /* of SCNetworkProtocolRef's */SCNetworkServiceCopyProtocols(SCNetworkServiceRef service){ CFMutableArrayRef array; CFIndex n; CFSetRef non_protocol_entities; CFStringRef path; CFDictionaryRef protocols; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity protocols = SCPreferencesPathGetValue(servicePrivate->prefs, path); CFRelease(path);
if (!isA_CFDictionary(protocols)) { // if corrupt prefs _SCErrorSet(kSCStatusFailed); return NULL; }
non_protocol_entities = _copyInterfaceEntityTypes(protocols);
array = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
n = CFDictionaryGetCount(protocols); if (n > 0) { CFIndex i; const void * keys_q[N_QUICK]; const void ** keys = keys_q; const void * vals_q[N_QUICK]; const void ** vals = vals_q;
if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); vals = CFAllocatorAllocate(NULL, n * sizeof(CFPropertyListRef), 0); } CFDictionaryGetKeysAndValues(protocols, keys, vals); for (i = 0; i < n; i++) { SCNetworkProtocolPrivateRef protocolPrivate;
if (!isA_CFDictionary(vals[i])) { // if it's not a dictionary then it can't be a protocol entity continue; }
if (CFSetContainsValue(non_protocol_entities, keys[i])) { // skip any non-protocol (interface) entities continue; }
protocolPrivate = __SCNetworkProtocolCreatePrivate(NULL, keys[i], service); CFArrayAppendValue(array, (SCNetworkProtocolRef)protocolPrivate);
CFRelease(protocolPrivate); } if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, vals); } }
CFRelease(non_protocol_entities);
return array;}
static Boolean__SCNetworkServiceSetInterfaceEntity(SCNetworkServiceRef service, SCNetworkInterfaceRef interface){ CFDictionaryRef entity; Boolean ok; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service kSCEntNetInterface); // entity entity = __SCNetworkInterfaceCopyInterfaceEntity(interface); ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, entity); CFRelease(entity); CFRelease(path);
return ok;}
SCNetworkServiceRefSCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface){ CFArrayRef components; CFArrayRef interface_config; CFStringRef interface_name; SCNetworkInterfaceRef newInterface; CFStringRef path; CFStringRef prefix; CFStringRef serviceID; SCNetworkServicePrivateRef servicePrivate; CFArrayRef supported_protocols;
if (!isA_SCNetworkInterface(interface)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
// only allow network interfaces which support one or more protocols // to be added to a service. The one exception is that we allow // third-party interface types to be configured. supported_protocols = SCNetworkInterfaceGetSupportedProtocolTypes(interface); if (supported_protocols == NULL) { CFStringRef interface_type;
interface_type = SCNetworkInterfaceGetInterfaceType(interface); if (CFStringFind(interface_type, CFSTR("."), 0).location == kCFNotFound) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; } }
// do not allow creation of a network service if the interface is a // member of a bond or bridge if (__SCNetworkInterfaceIsMember(prefs, interface)) { _SCErrorSet(kSCStatusKeyExists); return NULL; }
// establish the service prefix = SCPreferencesPathKeyCreateNetworkServices(NULL); path = __SCPreferencesPathCreateUniqueChild_WithMoreSCFCompatibility(prefs, prefix); if (path == NULL) path = SCPreferencesPathCreateUniqueChild(prefs, prefix); CFRelease(prefix); if (path == NULL) { return NULL; }
components = CFStringCreateArrayBySeparatingStrings(NULL, path, CFSTR("/")); CFRelease(path);
serviceID = CFArrayGetValueAtIndex(components, 2); servicePrivate = __SCNetworkServiceCreatePrivate(NULL, prefs, serviceID, NULL); CFRelease(components);
// duplicate the interface and associate the copy with the new service newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, interface, prefs, serviceID); servicePrivate->interface = newInterface;
// establish "default" configuration(s) for the interface for (interface = newInterface; interface != NULL; interface = SCNetworkInterfaceGetInterface(interface)) { SCNetworkInterfaceRef childInterface; CFStringRef childInterfaceType = NULL; CFDictionaryRef config; CFStringRef interfaceType;
interfaceType = SCNetworkInterfaceGetInterfaceType(interface); childInterface = SCNetworkInterfaceGetInterface(interface); if (childInterface != NULL) { childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface); }
config = __copyInterfaceTemplate(interfaceType, childInterfaceType); if (config != NULL) { if (CFEqual(interfaceType, kSCNetworkInterfaceTypeBluetooth) || CFEqual(interfaceType, kSCNetworkInterfaceTypeIrDA ) || CFEqual(interfaceType, kSCNetworkInterfaceTypeModem ) || CFEqual(interfaceType, kSCNetworkInterfaceTypeSerial ) || CFEqual(interfaceType, kSCNetworkInterfaceTypeWWAN )) { CFDictionaryRef overrides;
overrides = __SCNetworkInterfaceGetTemplateOverrides(interface, kSCNetworkInterfaceTypeModem);
// a ConnectionScript (and related keys) from the interface // should trump the settings from the configuration template. if (isA_CFDictionary(overrides)) { CFMutableDictionaryRef newConfig;
newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); if (CFDictionaryContainsKey(overrides, kSCPropNetModemConnectionScript)) { CFDictionaryRemoveValue(newConfig, kSCPropNetModemConnectionPersonality); CFDictionaryRemoveValue(newConfig, kSCPropNetModemConnectionScript); CFDictionaryRemoveValue(newConfig, kSCPropNetModemDeviceVendor); CFDictionaryRemoveValue(newConfig, kSCPropNetModemDeviceModel); } CFDictionaryApplyFunction(overrides, mergeDict, newConfig); CFRelease(config); config = newConfig; } } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP) || CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { CFDictionaryRef overrides;
overrides = __SCNetworkInterfaceGetTemplateOverrides(interface, kSCNetworkInterfaceTypePPP); if (isA_CFDictionary(overrides)) { CFMutableDictionaryRef newConfig;
newConfig = CFDictionaryCreateMutableCopy(NULL, 0, config); CFDictionaryApplyFunction(overrides, mergeDict, newConfig); CFRelease(config); config = newConfig; } }
if (!__SCNetworkInterfaceSetConfiguration(interface, NULL, config, TRUE)) { SC_log(LOG_INFO, "__SCNetworkInterfaceSetConfiguration failed(), interface=%@, type=NULL", interface); } CFRelease(config); } }
// add the interface [entity] to the service (void) __SCNetworkServiceSetInterfaceEntity((SCNetworkServiceRef)servicePrivate, servicePrivate->interface);
// push the [deep] interface configuration into the service. interface_config = __SCNetworkInterfaceCopyDeepConfiguration(NULL, servicePrivate->interface); __SCNetworkInterfaceSetDeepConfiguration(NULL, servicePrivate->interface, interface_config); if (interface_config != NULL) CFRelease(interface_config);
// set the service name to match that of the associated interface // // Note: It might seem a bit odd to call SCNetworkServiceGetName // followed by an immediate call to SCNetworkServiceSetName. The // trick here is that if no name has previously been set, the // "get" function will return the name of the associated interface. // // ... and we "set" a name to ensure that applications that do // not use the APIs will still find a UserDefinedName property // in the SCDynamicStore. // interface_name = SCNetworkServiceGetName((SCNetworkServiceRef)servicePrivate); if (interface_name != NULL) { (void) SCNetworkServiceSetName((SCNetworkServiceRef)servicePrivate, interface_name); }
SC_log(LOG_DEBUG, "SCNetworkServiceCreate(): %@", servicePrivate);
return (SCNetworkServiceRef)servicePrivate;}
BooleanSCNetworkServiceEstablishDefaultConfiguration(SCNetworkServiceRef service){ CFIndex i; SCNetworkInterfaceRef interface; CFIndex n; Boolean ok; CFArrayRef protocolTypes; CFStringRef rankStr; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
interface = SCNetworkServiceGetInterface(service); if (interface == NULL) { return FALSE; }
protocolTypes = SCNetworkInterfaceGetSupportedProtocolTypes(interface); n = (protocolTypes != NULL) ? CFArrayGetCount(protocolTypes) : 0; for (i = 0; i < n; i++) { CFStringRef protocolType;
protocolType = CFArrayGetValueAtIndex(protocolTypes, i); ok = SCNetworkServiceAddProtocolType(service, protocolType); if (!ok) { SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration(): could not add protocol \"%@\"", protocolType); } }
rankStr = __SCNetworkInterfaceGetTemplateOverrides(interface, kSCPropNetServicePrimaryRank); if (isA_CFString(rankStr)) { SCNetworkServicePrimaryRank rank;
ok = __str_to_rank(rankStr, &rank); if (!ok) { SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration(): unknown rank \"%@\"", rankStr); goto done; }
ok = SCNetworkServiceSetPrimaryRank(service, rank); if (!ok) { SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration(): could not set rank \"%@\"", rankStr); goto done; } }
done :
return TRUE;}
BooleanSCNetworkServiceGetEnabled(SCNetworkServiceRef service){ Boolean enabled; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity enabled = __getPrefsEnabled(servicePrivate->prefs, path); CFRelease(path);
return enabled;}
SCNetworkInterfaceRefSCNetworkServiceGetInterface(SCNetworkServiceRef service){ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
if (servicePrivate->interface == NULL) { CFDictionaryRef entity; CFStringRef path;
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service kSCEntNetInterface); // entity entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); CFRelease(path);
if (isA_CFDictionary(entity)) { servicePrivate->interface = _SCNetworkInterfaceCreateWithEntity(NULL, entity, service); } }
return servicePrivate->interface;}
CFStringRefSCNetworkServiceGetName(SCNetworkServiceRef service){ CFDictionaryRef entity; SCNetworkInterfaceRef interface; CFStringRef name = NULL; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; Boolean useSystemInterfaces = TRUE;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
if (servicePrivate->name != NULL) { return servicePrivate->name; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); CFRelease(path);
useSystemInterfaces = ((__SCPreferencesUsingDefaultPrefs(servicePrivate->prefs)) && !__SCPreferencesGetLimitSCNetworkConfiguration(servicePrivate->prefs));
if (isA_CFDictionary(entity)) { name = CFDictionaryGetValue(entity, kSCPropUserDefinedName); if (isA_CFString(name)) { servicePrivate->name = CFRetain(name); if (!useSystemInterfaces) { return servicePrivate->name; } } }
interface = SCNetworkServiceGetInterface(service); while (interface != NULL) { SCNetworkInterfaceRef childInterface; CFStringRef interfaceType;
interfaceType = SCNetworkInterfaceGetInterfaceType(interface); if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { break; }
childInterface = SCNetworkInterfaceGetInterface(interface); if ((childInterface == NULL) || CFEqual(childInterface, kSCNetworkInterfaceIPv4)) { break; }
interface = childInterface; }
if (interface != NULL) { int i; CFStringRef interface_name = NULL; CFStringRef suffix = NULL;
// // check if the [stored] service name matches the non-localized interface // name. If so, return the localized name. // // Also, the older "Built-in XXX" interface names are too long for the // current UI. If we find that the [stored] service name matches the older // name, return the newer (and shorter) localized name. // // Note: the user/admin will no longer be able to set the service name // to "Built-in Ethernet". // for (i = 0; i < 3; i++) { if (servicePrivate->name == NULL) { // if no [stored] service name to compare break; }
switch (i) { case 0 : // compare the non-localized interface name interface_name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); if (interface_name != NULL) { CFRetain(interface_name); } break;#if !TARGET_OS_IPHONE case 1 : // compare the older "Built-in XXX" localized name interface_name = __SCNetworkInterfaceCopyXLocalizedDisplayName(interface); break; case 2 : // compare the older "Built-in XXX" non-localized name interface_name = __SCNetworkInterfaceCopyXNonLocalizedDisplayName(interface); break;#else // !TARGET_OS_IPHONE default : continue;#endif // !TARGET_OS_IPHONE }
if (interface_name != NULL) { Boolean match = FALSE;
if (CFEqual(name, interface_name)) { // if service name matches the OLD localized // interface name match = TRUE; } else if (CFStringHasPrefix(name, interface_name)) { CFIndex prefixLen = CFStringGetLength(interface_name); CFIndex suffixLen = CFStringGetLength(name);
suffix = CFStringCreateWithSubstring(NULL, name, CFRangeMake(prefixLen, suffixLen - prefixLen)); match = TRUE; } CFRelease(interface_name);
if (match) { CFRelease(servicePrivate->name); servicePrivate->name = NULL; break; } } }
// // if the service name has not been set, use the localized interface name // if (servicePrivate->name == NULL) { interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface); if (interface_name != NULL) { if (suffix != NULL) { servicePrivate->name = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), interface_name, suffix); } else { servicePrivate->name = CFRetain(interface_name); } } } if (suffix != NULL) CFRelease(suffix); }
return servicePrivate->name;}
CFStringRefSCNetworkServiceGetServiceID(SCNetworkServiceRef service){ SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
return servicePrivate->serviceID;}
CFTypeIDSCNetworkServiceGetTypeID(void){ pthread_once(&initialized, __SCNetworkServiceInitialize); /* initialize runtime */ return __kSCNetworkServiceTypeID;}
BooleanSCNetworkServiceRemove(SCNetworkServiceRef service){ Boolean ok = FALSE; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; CFArrayRef sets;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceRemove() w/removed service\n service = %@", service); _SC_crash_once("SCNetworkServiceRemove() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
// remove service from all sets
sets = SCNetworkSetCopyAll(servicePrivate->prefs); if (sets != NULL) { CFIndex n;
n = CFArrayGetCount(sets); for (CFIndex i = 0; i < n; i++) { SCNetworkSetRef set;
set = CFArrayGetValueAtIndex(sets, i); ok = SCNetworkSetRemoveService(set, service); if (!ok && (SCError() != kSCStatusNoKey)) { CFRelease(sets); return ok; } } CFRelease(sets); }
// remove service
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path); CFRelease(path);
if (ok) { SC_log(LOG_DEBUG, "SCNetworkServiceRemove(): %@", service); }
return ok;}
BooleanSCNetworkServiceRemoveProtocolType(SCNetworkServiceRef service, CFStringRef protocolType){ CFDictionaryRef entity; Boolean ok = FALSE; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceRemoveProtocolType() w/removed service\n service = %@\n protocol = %@", service, protocolType); _SC_crash_once("SCNetworkServiceRemoveProtocolType() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkProtocolIsValidType(protocolType)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service protocolType); // entity
entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); if (entity == NULL) { // if "protocol" does not exist _SCErrorSet(kSCStatusNoKey); goto done; }
ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path);
done :
if (ok) { SC_log(LOG_DEBUG, "SCNetworkServiceRemoveProtocolType(): %@, %@", service, protocolType); }
CFRelease(path); return ok;}
BooleanSCNetworkServiceSetEnabled(SCNetworkServiceRef service, Boolean enabled){ Boolean ok; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceSetEnabled() w/removed service\n service = %@", service); _SC_crash_once("SCNetworkProtocolSetEnabled() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
// make sure that we do not enable a network service if the // associated interface is a member of a bond or bridge. if (enabled) { SCNetworkInterfaceRef interface;
interface = SCNetworkServiceGetInterface(service); if ((interface != NULL) && __SCNetworkInterfaceIsMember(servicePrivate->prefs, interface)) { _SCErrorSet(kSCStatusKeyExists); return FALSE; } }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity ok = __setPrefsEnabled(servicePrivate->prefs, path, enabled); CFRelease(path);
if (ok) { SC_log(LOG_DEBUG, "SCNetworkServiceSetEnabled(): %@ -> %s", service, enabled ? "Enabled" : "Disabled"); }
return ok;}
BooleanSCNetworkServiceSetName(SCNetworkServiceRef service, CFStringRef name){ CFDictionaryRef entity; Boolean ok = FALSE; CFStringRef path; CFStringRef saveName = NULL; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceSetName() w/removed service\n service = %@\n name = %@", service, name != NULL ? name : CFSTR("<NULL>")); _SC_crash_once("SCNetworkServiceSetName() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (name != NULL) { if (!isA_CFString(name)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } saveName = CFRetain(name); }
if (name != NULL) { SCNetworkInterfaceRef interface;
interface = SCNetworkServiceGetInterface(service); while (interface != NULL) { SCNetworkInterfaceRef childInterface;
childInterface = SCNetworkInterfaceGetInterface(interface); if (childInterface == NULL) { break; }
interface = childInterface; }
if (interface != NULL) { CFStringRef interface_name;
interface_name = SCNetworkInterfaceGetLocalizedDisplayName(interface); if (interface_name != NULL) { if (CFEqual(name, interface_name)) { // if service name matches the localized interface name // then store the non-localized name. interface_name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); if (interface_name != NULL) { CFRelease(saveName); saveName = CFRetain(interface_name); } } else if (CFStringHasPrefix(name, interface_name)) { CFIndex prefixLen = CFStringGetLength(interface_name); CFStringRef suffix; CFIndex suffixLen = CFStringGetLength(name);
// if service name matches the localized interface name plus // a few extra characters) then store the non-localized name with // the same suffix. suffix = CFStringCreateWithSubstring(NULL, name, CFRangeMake(prefixLen, suffixLen - prefixLen)); interface_name = __SCNetworkInterfaceGetNonLocalizedDisplayName(interface); if (interface_name != NULL) { CFRelease(saveName); saveName = CFStringCreateWithFormat(NULL, NULL, CFSTR("%@%@"), interface_name, suffix); } CFRelease(suffix); } } } }
#define PREVENT_DUPLICATE_SERVICE_NAMES#ifdef PREVENT_DUPLICATE_SERVICE_NAMES if (name != NULL) { CFArrayRef sets;
// ensure that each service is uniquely named within its sets
sets = SCNetworkSetCopyAll(servicePrivate->prefs); if (sets != NULL) { CFIndex set_index; CFIndex set_count;
set_count = CFArrayGetCount(sets); for (set_index = 0; set_index < set_count; set_index++) { CFIndex service_index; Boolean isDup = FALSE; Boolean isMember = FALSE; CFIndex service_count; CFArrayRef services; SCNetworkSetRef set = CFArrayGetValueAtIndex(sets, set_index);
services = SCNetworkSetCopyServices(set);
service_count = CFArrayGetCount(services); for (service_index = 0; service_index < service_count; service_index++) { CFStringRef otherID; CFStringRef otherName; SCNetworkServiceRef otherService;
otherService = CFArrayGetValueAtIndex(services, service_index);
otherID = SCNetworkServiceGetServiceID(otherService); if (CFEqual(servicePrivate->serviceID, otherID)) { // if the service is a member of this set isMember = TRUE; continue; }
otherName = SCNetworkServiceGetName(otherService); if ((otherName != NULL) && CFEqual(name, otherName)) { isDup = TRUE; continue; } }
CFRelease(services);
if (isMember && isDup) { /* * if this service is a member of the set and * the "name" is not unique. */ CFRelease(sets); if (saveName != NULL) CFRelease(saveName); _SCErrorSet(kSCStatusKeyExists); return FALSE; } }
CFRelease(sets); } }#endif /* PREVENT_DUPLICATE_SERVICE_NAMES */
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); if (isA_CFDictionary(entity) || ((entity == NULL) && (name != NULL))) { CFMutableDictionaryRef newEntity;
if (entity != NULL) { newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); } else { newEntity = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } if (saveName != NULL) { CFDictionarySetValue(newEntity, kSCPropUserDefinedName, saveName); } else { CFDictionaryRemoveValue(newEntity, kSCPropUserDefinedName); } ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity); CFRelease(newEntity); } CFRelease(path); if (saveName != NULL) CFRelease(saveName);
if (servicePrivate->name != NULL) CFRelease(servicePrivate->name); if (name != NULL) CFRetain(name); servicePrivate->name = name;
if (ok) { SC_log(LOG_DEBUG, "SCNetworkServiceSetName(): %@", service); }
return ok;}
#pragma mark -#pragma mark SCNetworkService SPIs
__private_extern__Boolean__SCNetworkServiceExists(SCNetworkServiceRef service){ CFDictionaryRef entity; CFStringRef path; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (servicePrivate->prefs == NULL) { // if no prefs return FALSE; }
path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service kSCEntNetInterface); // entity entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); CFRelease(path);
if (!isA_CFDictionary(entity)) { // a "service" must have an "interface" return FALSE; }
return TRUE;}
SCNetworkServicePrimaryRankSCNetworkServiceGetPrimaryRank(SCNetworkServiceRef service){ CFDictionaryRef entity; Boolean ok = TRUE; CFStringRef path; SCNetworkServicePrimaryRank rank = kSCNetworkServicePrimaryRankDefault; CFStringRef rankStr = NULL; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service)) { _SCErrorSet(kSCStatusInvalidArgument); return rank; }
if (servicePrivate->prefs != NULL) { path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, servicePrivate->serviceID, NULL); entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); CFRelease(path); if (isA_CFDictionary(entity)) { rankStr = CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank); ok = __str_to_rank(rankStr, &rank); } } else if (servicePrivate->store != NULL) { path = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, servicePrivate->serviceID, NULL); entity = SCDynamicStoreCopyValue(servicePrivate->store, path); CFRelease(path); if (entity != NULL) { if (isA_CFDictionary(entity)) { rankStr = CFDictionaryGetValue(entity, kSCPropNetServicePrimaryRank); ok = __str_to_rank(rankStr, &rank); } CFRelease(entity); } } else { _SCErrorSet(kSCStatusInvalidArgument); return rank; }
if (!ok) { rank = kSCNetworkServicePrimaryRankDefault; _SCErrorSet(kSCStatusInvalidArgument); } else if (rank == kSCNetworkServicePrimaryRankDefault) { _SCErrorSet(kSCStatusOK); }
return rank;}
BooleanSCNetworkServiceSetPrimaryRank(SCNetworkServiceRef service, SCNetworkServicePrimaryRank newRank){ Boolean ok; CFDictionaryRef entity; CFMutableDictionaryRef newEntity; CFStringRef path = NULL; CFStringRef rankStr = NULL; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if ((servicePrivate->prefs != NULL) && !__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceSetPrimaryRank() w/removed\n service = %@", service); _SC_crash_once("SCNetworkServiceSetPrimaryRank() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
ok = __rank_to_str(newRank, &rankStr); if (!ok) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (servicePrivate->prefs != NULL) { switch (newRank) { case kSCNetworkServicePrimaryRankDefault: case kSCNetworkServicePrimaryRankNever: case kSCNetworkServicePrimaryRankScoped: path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, servicePrivate->serviceID, NULL); entity = SCPreferencesPathGetValue(servicePrivate->prefs, path); if (entity != NULL) { if (!isA_CFDictionary(entity)) { // if corrupt prefs _SCErrorSet(kSCStatusFailed); goto done; } newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); } else { newEntity = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } if (rankStr != NULL) { CFDictionarySetValue(newEntity, kSCPropNetServicePrimaryRank, rankStr); } else { CFDictionaryRemoveValue(newEntity, kSCPropNetServicePrimaryRank); } if (CFDictionaryGetCount(newEntity) > 0) { ok = SCPreferencesPathSetValue(servicePrivate->prefs, path, newEntity); } else { ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, path); } CFRelease(newEntity); if (!ok) { goto done; } break; default: _SCErrorSet(kSCStatusInvalidArgument); return FALSE; } } else if (servicePrivate->store != NULL) { path = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, servicePrivate->serviceID, NULL); entity = SCDynamicStoreCopyValue(servicePrivate->store, path); if (entity != NULL) { if (!isA_CFDictionary(entity)) { // if corrupt prefs CFRelease(entity); _SCErrorSet(kSCStatusFailed); goto done; } newEntity = CFDictionaryCreateMutableCopy(NULL, 0, entity); CFRelease(entity); } else { newEntity = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } if (rankStr != NULL) { CFDictionarySetValue(newEntity, kSCPropNetServicePrimaryRank, rankStr); } else { CFDictionaryRemoveValue(newEntity, kSCPropNetServicePrimaryRank); } if (CFDictionaryGetCount(newEntity) > 0) { ok = SCDynamicStoreSetValue(servicePrivate->store, path, newEntity); } else { ok = SCDynamicStoreRemoveValue(servicePrivate->store, path); } CFRelease(newEntity); if (!ok) { goto done; } } else { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
done :
if (path != NULL) CFRelease(path); return ok;}
Boolean_SCNetworkServiceIsVPN(SCNetworkServiceRef service){ SCNetworkInterfaceRef interface; CFStringRef interfaceType;
interface = SCNetworkServiceGetInterface(service); if (interface == NULL) { return FALSE; }
interfaceType = SCNetworkInterfaceGetInterfaceType(interface); if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { interface = SCNetworkInterfaceGetInterface(interface); if (interface == NULL) { return FALSE; }
interfaceType = SCNetworkInterfaceGetInterfaceType(interface); if (CFEqual(interfaceType, kSCNetworkInterfaceTypeL2TP)) { return TRUE; }#pragma GCC diagnostic push#pragma GCC diagnostic ignored "-Wdeprecated" if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPTP)) { return TRUE; }#pragma GCC diagnostic pop } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeVPN)) { return TRUE; } else if (CFEqual(interfaceType, kSCNetworkInterfaceTypeIPSec)) { return TRUE; }
return FALSE;}
BooleanSCNetworkServiceSetExternalID(SCNetworkServiceRef service, CFStringRef identifierDomain, CFStringRef identifier){ CFStringRef prefs_path; CFDictionaryRef service_dictionary; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service; Boolean success = FALSE; CFStringRef prefixed_domain;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL) || !isA_CFString(identifierDomain)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "SCNetworkServiceSetExternalID() w/removed\n service = %@\n id = %@", service, identifier); _SC_crash_once("SCNetworkServiceSetExternalID() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (identifier != NULL && !isA_CFString(identifier)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
prefixed_domain = CFStringCreateWithFormat(NULL, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX, identifierDomain);
prefs_path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, servicePrivate->serviceID, NULL);
service_dictionary = SCPreferencesPathGetValue(servicePrivate->prefs, prefs_path); if (isA_CFDictionary(service_dictionary) || ((service_dictionary == NULL) && (identifier != NULL))) { CFMutableDictionaryRef new_service_dictionary;
if (service_dictionary != NULL) { new_service_dictionary = CFDictionaryCreateMutableCopy(NULL, 0, service_dictionary); } else { new_service_dictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); }
if (identifier != NULL) { CFDictionarySetValue(new_service_dictionary, prefixed_domain, identifier); } else { CFDictionaryRemoveValue(new_service_dictionary, prefixed_domain); } success = SCPreferencesPathSetValue(servicePrivate->prefs, prefs_path, new_service_dictionary); CFRelease(new_service_dictionary); } CFRelease(prefs_path);
if (identifier != NULL) { if (servicePrivate->externalIDs == NULL) { servicePrivate->externalIDs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFDictionarySetValue(servicePrivate->externalIDs, prefixed_domain, identifier); } else { if (servicePrivate->externalIDs != NULL) { CFDictionaryRemoveValue(servicePrivate->externalIDs, prefixed_domain); } }
CFRelease(prefixed_domain);
if (!success) { _SCErrorSet(kSCStatusFailed); }
return success;}
CFStringRefSCNetworkServiceCopyExternalID(SCNetworkServiceRef service, CFStringRef identifierDomain){ CFStringRef identifier = NULL; CFStringRef prefixed_domain; SCNetworkServicePrivateRef service_private = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (service_private->prefs == NULL) || !isA_CFString(identifierDomain)) { _SCErrorSet(kSCStatusInvalidArgument); return NULL; }
prefixed_domain = CFStringCreateWithFormat(NULL, 0, CFSTR("%s%@"), EXTERNAL_ID_DOMAIN_PREFIX, identifierDomain);
if (service_private->externalIDs != NULL) { identifier = CFDictionaryGetValue(service_private->externalIDs, prefixed_domain); if (identifier != NULL) { CFRetain(identifier); } }
if (identifier == NULL) { CFStringRef prefs_path; CFDictionaryRef service_dictionary;
prefs_path = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, service_private->serviceID, NULL);
service_dictionary = SCPreferencesPathGetValue(service_private->prefs, prefs_path); if (isA_CFDictionary(service_dictionary)) { identifier = CFDictionaryGetValue(service_dictionary, prefixed_domain); if (identifier != NULL) { CFRetain(identifier); if (service_private->externalIDs == NULL) { service_private->externalIDs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } CFDictionarySetValue(service_private->externalIDs, prefixed_domain, identifier); } } CFRelease(prefs_path); }
CFRelease(prefixed_domain);
if (identifier == NULL) { _SCErrorSet(kSCStatusNoKey); }
return identifier;}
typedef struct { CFStringRef oldServiceID; CFStringRef newServiceID;} serviceContext, *serviceContextRef;
static voidreplaceServiceID(const void *value, void *context){ CFStringRef link = NULL; CFStringRef oldLink; CFMutableArrayRef newServiceOrder; CFStringRef path; serviceContextRef service_context = (serviceContextRef)context; CFArrayRef serviceOrder = NULL; SCNetworkSetRef set = (SCNetworkSetRef)value; SCNetworkSetPrivateRef setPrivate = (SCNetworkSetPrivateRef)set;
// update service order serviceOrder = SCNetworkSetGetServiceOrder(set); if ((isA_CFArray(serviceOrder) != NULL) && CFArrayContainsValue(serviceOrder, CFRangeMake(0, CFArrayGetCount(serviceOrder)), service_context->oldServiceID)) { CFIndex count; CFIndex serviceOrderIndex;
// replacing all instances of old service ID with new one newServiceOrder = CFArrayCreateMutableCopy(NULL, 0, serviceOrder); count = CFArrayGetCount(newServiceOrder); for (serviceOrderIndex = 0; serviceOrderIndex < count; serviceOrderIndex++) { CFStringRef serviceID;
serviceID = CFArrayGetValueAtIndex(newServiceOrder, serviceOrderIndex); if (CFEqual(serviceID, service_context->oldServiceID)) { CFArraySetValueAtIndex(newServiceOrder, serviceOrderIndex, service_context->newServiceID); } } SCNetworkSetSetServiceOrder(set, newServiceOrder); CFRelease(newServiceOrder); }
// check if service with old serviceID is part of the set path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator setPrivate->setID, // set service_context->oldServiceID, // service NULL); // entity oldLink = SCPreferencesPathGetLink(setPrivate->prefs, path); if (oldLink == NULL) { // don't make any changes if service with old serviceID is not found goto done; }
// remove link between "set" and old "service" (void) SCPreferencesPathRemoveValue(setPrivate->prefs, path); CFRelease(path);
// create the link between "set" and the "service" path = SCPreferencesPathKeyCreateSetNetworkServiceEntity(NULL, // allocator setPrivate->setID, // set service_context->newServiceID, // service NULL); // entity link = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator service_context->newServiceID, // service NULL); // entity (void) SCPreferencesPathSetLink(setPrivate->prefs, path, link);
done:
if (path != NULL) { CFRelease(path); } if (link != NULL) { CFRelease(link); }
return;}
Boolean_SCNetworkServiceSetServiceID(SCNetworkServiceRef service, CFStringRef newServiceID){ CFArrayRef allSets = NULL; CFDictionaryRef entity; CFStringRef newPath; Boolean ok = FALSE; CFStringRef oldPath = NULL; serviceContext service_context; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (!isA_SCNetworkService(service) || (servicePrivate->prefs == NULL)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (!isA_CFString(newServiceID)) { _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
if (CFEqual(newServiceID, servicePrivate->serviceID)) { // no work needs to be done if new service ID is equal to current service ID return TRUE; }
if (!__SCNetworkServiceExists(service)) { SC_log(LOG_ERR, "_SCNetworkServiceSetServiceID() w/removed service\n service = %@\n serviceID = %@", service, newServiceID); _SC_crash_once("_SCNetworkServiceSetServiceID() w/removed service", NULL, NULL); _SCErrorSet(kSCStatusInvalidArgument); return FALSE; }
newPath = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator newServiceID, // service NULL); // entity entity = SCPreferencesPathGetValue(servicePrivate->prefs, newPath); if (isA_CFDictionary(entity)) { // if the new service already exists _SCErrorSet(kSCStatusKeyExists); goto done; }
oldPath = SCPreferencesPathKeyCreateNetworkServiceEntity(NULL, // allocator servicePrivate->serviceID, // service NULL); // entity entity = SCPreferencesPathGetValue(servicePrivate->prefs, oldPath); if (!isA_CFDictionary(entity)) { // if the service has already been removed _SCErrorSet(kSCStatusNoKey); goto done; }
ok = SCPreferencesPathSetValue(servicePrivate->prefs, newPath, entity); if (!ok) goto done;
ok = SCPreferencesPathRemoveValue(servicePrivate->prefs, oldPath); if (!ok) goto done;
allSets = SCNetworkSetCopyAll(servicePrivate->prefs);
service_context.newServiceID = newServiceID; service_context.oldServiceID = servicePrivate->serviceID;
// find all sets w/oldServiceID and update // ... and update the serviceOrder CFArrayApplyFunction(allSets, CFRangeMake(0, CFArrayGetCount(allSets)), replaceServiceID, &service_context);
if (servicePrivate->interface != NULL) { SCNetworkInterfaceRef newInterface;
// duplicate the interface and associate the copy with the new service ID newInterface = (SCNetworkInterfaceRef)__SCNetworkInterfaceCreateCopy(NULL, servicePrivate->interface, servicePrivate->prefs, newServiceID); CFRelease(servicePrivate->interface); servicePrivate->interface = newInterface; }
SC_log(LOG_DEBUG, "_SCNetworkServiceSetServiceID(): %@ --> %@", service, newServiceID);
// replace serviceID with new one CFRetain(newServiceID); CFRelease(servicePrivate->serviceID); servicePrivate->serviceID = newServiceID;
done:
if (oldPath != NULL) { CFRelease(oldPath); } if (newPath != NULL) { CFRelease(newPath); } if (allSets != NULL) { CFRelease(allSets); }
return ok;}
#define kVPNProtocolPayloadInfo CFSTR("com.apple.payload")#define kSCEntNetLoginWindowEAPOL CFSTR("EAPOL.LoginWindow")
static voidcopyInterfaceConfiguration(SCNetworkServiceRef oldService, SCNetworkServiceRef newService){ SCNetworkInterfaceRef oldInterface; SCNetworkInterfaceRef newInterface;
oldInterface = SCNetworkServiceGetInterface(oldService); newInterface = SCNetworkServiceGetInterface(newService);
while (oldInterface != NULL) { CFDictionaryRef configuration; CFStringRef interfaceType;
if (newInterface == NULL) { // oops ... interface layering does not match return; }
// copy interface configuration configuration = SCNetworkInterfaceGetConfiguration(oldInterface);
if ((configuration != NULL) || (SCError() == kSCStatusOK)) { if (!SCNetworkInterfaceSetConfiguration(newInterface, configuration)) { SC_log(LOG_INFO, "problem setting interface configuration"); }
}
// special case: PPP/L2TP + IPSec interfaceType = SCNetworkInterfaceGetInterfaceType(oldInterface); if (CFEqual(interfaceType, kSCNetworkInterfaceTypePPP)) { SCNetworkInterfaceRef childInterface;
childInterface = SCNetworkInterfaceGetInterface(oldInterface); if (childInterface != NULL) { CFStringRef childInterfaceType;
childInterfaceType = SCNetworkInterfaceGetInterfaceType(childInterface);
if (CFEqual(childInterfaceType, kSCNetworkInterfaceTypeL2TP)) { configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCEntNetIPSec); if ((configuration != NULL) || (SCError() == kSCStatusOK)) { if (!SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCEntNetIPSec, configuration)) { SC_log(LOG_INFO, "problem setting child interface configuration"); } } } } }
// special case: 802.1x configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCEntNetEAPOL); if ((configuration != NULL) || (SCError() == kSCStatusOK)) { (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCEntNetEAPOL, configuration); }
// special case: Managed Client configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kVPNProtocolPayloadInfo); if ((configuration != NULL) || (SCError() == kSCStatusOK)) { (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kVPNProtocolPayloadInfo, configuration); }
// special case: Network Pref configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCValNetPPPAuthProtocolEAP); if ((configuration != NULL) || (SCError() == kSCStatusOK)) { (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCValNetPPPAuthProtocolEAP, configuration); }
// special case: Remote Pref configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCEntNetLoginWindowEAPOL); if ((configuration != NULL) || (SCError() == kSCStatusOK)) { (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCEntNetLoginWindowEAPOL, configuration); }
// special case: Network Extension configuration = SCNetworkInterfaceGetExtendedConfiguration(oldInterface, kSCNetworkInterfaceTypeIPSec); if ((configuration != NULL) || (SCError() == kSCStatusOK)) { (void) SCNetworkInterfaceSetExtendedConfiguration(newInterface, kSCNetworkInterfaceTypeIPSec, configuration); }
oldInterface = SCNetworkInterfaceGetInterface(oldInterface); newInterface = SCNetworkInterfaceGetInterface(newInterface); }
return;}
__private_extern__void__SCNetworkServiceAddProtocolToService(SCNetworkServiceRef service, CFStringRef protocolType, CFDictionaryRef configuration, Boolean enabled){ Boolean ok; SCNetworkProtocolRef protocol;
protocol = SCNetworkServiceCopyProtocol(service, protocolType);
if ((protocol == NULL) && (SCError() == kSCStatusNoKey)) { ok = SCNetworkServiceAddProtocolType(service, protocolType); if (ok) { protocol = SCNetworkServiceCopyProtocol(service, protocolType); } } if (protocol != NULL) { SCNetworkProtocolSetConfiguration(protocol, configuration); SCNetworkProtocolSetEnabled(protocol, enabled); CFRelease(protocol); } return;}
__private_extern__Boolean__SCNetworkServiceMigrateNew(SCPreferencesRef prefs, SCNetworkServiceRef service, CFDictionaryRef bsdMapping, CFDictionaryRef setMapping, CFDictionaryRef serviceSetMapping){ CFStringRef deviceName = NULL; Boolean enabled; SCNetworkInterfaceRef interface = NULL; CFDictionaryRef interfaceEntity = NULL; CFMutableDictionaryRef interfaceEntityMutable = NULL; SCNetworkSetRef newSet = NULL; SCPreferencesRef ni_prefs = NULL; SCNetworkInterfaceRef ni_interface = NULL; SCNetworkInterfaceRef oldInterface = NULL; SCNetworkSetRef oldSet = NULL; SCNetworkServiceRef newService = NULL; CFStringRef serviceID = NULL; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef) service; CFArrayRef setList = NULL; Boolean success = FALSE; CFStringRef targetDeviceName = NULL; CFStringRef userDefinedName = NULL; CFStringRef userDefinedNameInterface = NULL; CFArrayRef protocols = NULL; CFStringRef subType;
if ((isA_SCNetworkService(service) == NULL) || (isA_SCNetworkInterface(servicePrivate->interface) == NULL) || (servicePrivate->prefs == NULL)) { goto done; } serviceID = servicePrivate->serviceID;
newService = SCNetworkServiceCopy(prefs, serviceID); if (newService != NULL) { // Cannot add service if it already exists SC_log(LOG_INFO, "Service already exists"); goto done; }
oldInterface = SCNetworkServiceGetInterface(service); interfaceEntity = __SCNetworkInterfaceCopyInterfaceEntity(oldInterface); if (interfaceEntity == NULL) { SC_log(LOG_INFO, "No interface entity"); goto done; } interfaceEntityMutable = CFDictionaryCreateMutableCopy(NULL, 0, interfaceEntity);
if (isA_CFDictionary(bsdMapping) != NULL) { deviceName = CFDictionaryGetValue(interfaceEntityMutable, kSCPropNetInterfaceDeviceName); if (isA_CFString(deviceName) != NULL) { targetDeviceName = CFDictionaryGetValue(bsdMapping, deviceName); if (targetDeviceName != NULL) { // update mapping CFDictionarySetValue(interfaceEntityMutable, kSCPropNetInterfaceDeviceName, targetDeviceName); ni_prefs = __SCPreferencesCreateNIPrefsFromPrefs(prefs); ni_interface = __SCNetworkInterfaceCreateWithNIPreferencesUsingBSDName(NULL, ni_prefs, targetDeviceName); if (ni_interface != NULL) { userDefinedNameInterface = __SCNetworkInterfaceGetUserDefinedName(ni_interface); } } } if (userDefinedNameInterface == NULL) { userDefinedNameInterface = CFDictionaryGetValue(interfaceEntityMutable, kSCPropUserDefinedName); } } subType = CFDictionaryGetValue(interfaceEntityMutable, kSCPropNetInterfaceSubType); interface = _SCNetworkInterfaceCreateWithEntity(NULL, interfaceEntityMutable, NULL); if (userDefinedNameInterface != NULL) { __SCNetworkInterfaceSetUserDefinedName(interface, userDefinedNameInterface); } // Supporting PPPoE subtype if (subType != NULL && CFEqual(subType, kSCValNetInterfaceSubTypePPPoE)) { SCNetworkInterfaceRef childInterface = SCNetworkInterfaceGetInterface(interface); if (childInterface != NULL) { __SCNetworkInterfaceSetUserDefinedName(childInterface, userDefinedNameInterface); } } newService = SCNetworkServiceCreate(prefs, interface); if (newService == NULL) { SC_log(LOG_INFO, "SCNetworkServiceCreate() failed"); goto done; }
enabled = SCNetworkServiceGetEnabled(service); if (!SCNetworkServiceSetEnabled(newService, enabled)) { SCNetworkServiceRemove(newService); SC_log(LOG_INFO, "SCNetworkServiceSetEnabled() failed"); goto done; }
if (!SCNetworkServiceEstablishDefaultConfiguration(newService)) { SCNetworkServiceRemove(newService); SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration() failed"); goto done; }
// Set service ID _SCNetworkServiceSetServiceID(newService, serviceID);
userDefinedName = SCNetworkServiceGetName(service); if ((userDefinedName != NULL) && !SCNetworkServiceSetName(newService, userDefinedName)) { SC_log(LOG_INFO, "SCNetworkServiceSetName(, %@) failed", userDefinedName); }
// Determine which sets to add service if (setMapping != NULL && serviceSetMapping != NULL) { setList = CFDictionaryGetValue(serviceSetMapping, service); if (setList != NULL) { for (CFIndex idx = 0; idx < CFArrayGetCount(setList); idx++) { oldSet = CFArrayGetValueAtIndex(setList, idx); newSet = CFDictionaryGetValue(setMapping, oldSet); if (newSet == NULL) { continue; }
if (!SCNetworkSetAddService(newSet, newService)) { SC_log(LOG_INFO, "SCNetworkSetAddService() failed"); } } } }
protocols = SCNetworkServiceCopyProtocols(service); if (protocols != NULL) {
for (CFIndex idx = 0; idx < CFArrayGetCount(protocols); idx++) { SCNetworkProtocolRef protocol = CFArrayGetValueAtIndex(protocols, idx); CFDictionaryRef configuration = SCNetworkProtocolGetConfiguration(protocol); CFStringRef protocolType = SCNetworkProtocolGetProtocolType(protocol); enabled = SCNetworkProtocolGetEnabled(protocol); __SCNetworkServiceAddProtocolToService(newService, protocolType, configuration, enabled); } CFRelease(protocols); }
copyInterfaceConfiguration(service, newService);
success = TRUE;done: if (interface != NULL) { CFRelease(interface); } if (interfaceEntity != NULL) { CFRelease(interfaceEntity); } if (interfaceEntityMutable != NULL) { CFRelease(interfaceEntityMutable); } if (newService != NULL) { CFRelease(newService); } if (ni_prefs != NULL) { CFRelease(ni_prefs); } if (ni_interface != NULL) { CFRelease(ni_interface); } return success;}
__private_extern__Boolean__SCNetworkServiceCreate(SCPreferencesRef prefs, SCNetworkInterfaceRef interface, CFStringRef userDefinedName){ SCNetworkSetRef currentSet = NULL; Boolean ok = FALSE; SCNetworkServiceRef service = NULL;
if (interface == NULL) { goto done; }
if (userDefinedName == NULL) { userDefinedName = __SCNetworkInterfaceGetUserDefinedName(interface); if (userDefinedName == NULL) { SC_log(LOG_INFO, "No userDefinedName"); goto done; } } service = SCNetworkServiceCreate(prefs, interface); if (service == NULL) { SC_log(LOG_INFO, "SCNetworkServiceCreate() failed: %s", SCErrorString(SCError())); } else { ok = SCNetworkServiceSetName(service, userDefinedName); if (!ok) { SC_log(LOG_INFO, "SCNetworkServiceSetName() failed: %s", SCErrorString(SCError())); SCNetworkServiceRemove(service); goto done; }
ok = SCNetworkServiceEstablishDefaultConfiguration(service); if (!ok) { SC_log(LOG_INFO, "SCNetworkServiceEstablishDefaultConfiguration() failed: %s", SCErrorString(SCError())); SCNetworkServiceRemove(service); goto done; } } currentSet = SCNetworkSetCopyCurrent(prefs); if (currentSet == NULL) { SC_log(LOG_INFO, "No current set"); if (service != NULL) { SCNetworkServiceRemove(service); } goto done; } if (service != NULL) { ok = SCNetworkSetAddService(currentSet, service); if (!ok) { SC_log(LOG_INFO, "Could not add service to the current set"); SCNetworkServiceRemove(service); goto done; } }
done: if (service != NULL) { CFRelease(service); } if (currentSet != NULL) { CFRelease(currentSet); } return ok;}
__private_extern__ Boolean__SCNetworkServiceIsPPTP(SCNetworkServiceRef service){ CFStringRef intfSubtype; SCNetworkServicePrivateRef servicePrivate = (SCNetworkServicePrivateRef)service;
if (servicePrivate == NULL || servicePrivate->interface == NULL) { return FALSE; }
intfSubtype = __SCNetworkInterfaceGetEntitySubType(servicePrivate->interface); if (intfSubtype == NULL) { return FALSE; }
#pragma GCC diagnostic push#pragma GCC diagnostic ignored "-Wdeprecated" if (CFEqual(intfSubtype, kSCValNetInterfaceSubTypePPTP)) { return TRUE; }#pragma GCC diagnostic pop
return FALSE;}