Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
14 kB · 535 lines
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536/* * Copyright (c) 2006, 2008, 2009, 2011-2019 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@ */
/* * SCNetworkSignature.c * - implementation of SCNetworkSignatureRef API that allows access to network identification information * *//* * Modification History * * November 6, 2006 Dieter Siegmund (dieter@apple.com) * - initial revision */
#include <netinet/in.h>#include <CoreFoundation/CFDictionary.h>#include <CoreFoundation/CFString.h>#include <CoreFoundation/CFArray.h>#include <CoreFoundation/CFRuntime.h>#include <SystemConfiguration/SCDynamicStore.h>#include <SystemConfiguration/SCValidation.h>#include <SystemConfiguration/SCPrivate.h>#include "SCNetworkSignature.h"#include "SCNetworkSignaturePrivate.h"#include <arpa/inet.h>#include <sys/types.h>#include <sys/socket.h>#include <net/if.h>#include <nw/private.h>
#pragma mark SCNetworkSignature Supporting APIs
static CFStringRefcreate_global_state_v4_key(void){ return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4);
}
static CFStringRefcreate_global_setup_v4_key(void){ return SCDynamicStoreKeyCreateNetworkGlobalEntity(NULL, kSCDynamicStoreDomainSetup, kSCEntNetIPv4);}
static CFStringRefcreate_ipv4_services_pattern(void){ return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4);}
static CFStringRefcreate_ipv6_services_pattern(void){ return SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv6);}
static CFDictionaryRefcopy_services_for_address_family(CFAllocatorRef alloc, int af){#pragma unused(alloc) CFDictionaryRef info; CFArrayRef patterns; CFStringRef pattern; CFStringRef prop;
prop = (af == AF_INET) ? kSCEntNetIPv4 : kSCEntNetIPv6; pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, kSCCompAnyRegex, prop); patterns = CFArrayCreate(NULL, (const void * *)&pattern, 1, &kCFTypeArrayCallBacks); CFRelease(pattern); info = SCDynamicStoreCopyMultiple(NULL, NULL, patterns); CFRelease(patterns);
return (info);}
static CF_RETURNS_RETAINED CFStringRefmy_IPAddressToCFString(int af, const void * src_p){ char ntopbuf[INET6_ADDRSTRLEN];
if (inet_ntop(af, src_p, ntopbuf, sizeof(ntopbuf)) != NULL) { return (CFStringCreateWithCString(NULL, ntopbuf, kCFStringEncodingASCII)); } return (NULL);}
#pragma mark -
#pragma mark SCNetworkSignature APIs
CFStringRefSCNetworkSignatureCopyActiveIdentifierForAddress(CFAllocatorRef alloc, const struct sockaddr * addr){#pragma unused(alloc) CFStringRef ident = NULL; CFDictionaryRef info = NULL; CFStringRef global_state_v4_key = NULL; CFDictionaryRef global_v4_state_dict = NULL; CFArrayRef keys = NULL; CFArrayRef patterns = NULL; in_addr_t s_addr; CFStringRef service = NULL; CFDictionaryRef service_dict = NULL; CFStringRef service_id = NULL; struct sockaddr_in * sin_p; CFStringRef v4_service_pattern = NULL;
/* only accept 0.0.0.0 (i.e. default) for now */ if (addr == NULL || addr->sa_family != AF_INET || addr->sa_len != sizeof(struct sockaddr_in)) { _SCErrorSet(kSCStatusInvalidArgument); goto done; }
/* ALIGN: force alignment */ sin_p = (struct sockaddr_in *)(void *)addr; memcpy(&s_addr, &sin_p->sin_addr.s_addr, sizeof(s_addr)); if (s_addr != 0) { _SCErrorSet(kSCStatusInvalidArgument); goto done; }
global_state_v4_key = create_global_state_v4_key(); keys = CFArrayCreate(NULL, (const void * *)&global_state_v4_key, 1, &kCFTypeArrayCallBacks);
v4_service_pattern = create_ipv4_services_pattern(); patterns = CFArrayCreate(NULL, (const void * *)&v4_service_pattern, 1, &kCFTypeArrayCallBacks);
info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
if (info == NULL || CFDictionaryGetCount(info) == 0) { goto done; }
global_v4_state_dict = CFDictionaryGetValue(info, global_state_v4_key);
if (isA_CFDictionary(global_v4_state_dict) == NULL) { goto done; }
service_id = CFDictionaryGetValue(global_v4_state_dict, kSCDynamicStorePropNetPrimaryService);
if (isA_CFString(service_id) == NULL) { goto done; }
service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, service_id, kSCEntNetIPv4);
service_dict = CFDictionaryGetValue(info, service);
if (isA_CFDictionary(service_dict) == NULL || CFDictionaryGetCount(service_dict) == 0) { goto done; }
ident = CFDictionaryGetValue(service_dict, kStoreKeyNetworkSignature); ident = isA_CFString(ident);done: if (ident != NULL) { CFRetain(ident); } else { _SCErrorSet(kSCStatusFailed); } if (info != NULL) { CFRelease(info); } if (global_state_v4_key != NULL) { CFRelease(global_state_v4_key); } if (service != NULL) { CFRelease(service); } if (keys != NULL) { CFRelease(keys); } if (patterns != NULL) { CFRelease(patterns); } if (v4_service_pattern != NULL) { CFRelease(v4_service_pattern); } return (ident);}
CFArrayRef /* of CFStringRef's */SCNetworkSignatureCopyActiveIdentifiers(CFAllocatorRef alloc){#pragma unused(alloc) CFMutableArrayRef active = NULL; CFIndex count = 0; CFStringRef global_setup_v4_key = NULL; CFDictionaryRef global_v4_dict; int i; CFDictionaryRef info = NULL; CFArrayRef keys = NULL; CFMutableArrayRef patterns = NULL; CFRange range; CFMutableDictionaryRef services_dict = NULL; CFArrayRef service_order; CFStringRef v4_service_pattern = NULL; CFStringRef v6_service_pattern = NULL; const void * * values = NULL;#define KEYS_STATIC_COUNT 10 const void * values_static[KEYS_STATIC_COUNT];
patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
global_setup_v4_key = create_global_setup_v4_key(); keys = CFArrayCreate(NULL, (const void * *)&global_setup_v4_key, 1, &kCFTypeArrayCallBacks);
v4_service_pattern = create_ipv4_services_pattern(); CFArrayAppendValue(patterns, v4_service_pattern);
v6_service_pattern = create_ipv6_services_pattern(); CFArrayAppendValue(patterns, v6_service_pattern);
info = SCDynamicStoreCopyMultiple(NULL, keys, patterns);
if (info == NULL || CFDictionaryGetCount(info) == 0) { goto done; }
services_dict = CFDictionaryCreateMutableCopy(NULL, 0, info); /* * The service_dict should only contain services and once each * service has been visited, it will be removed from the dictionary. */ CFDictionaryRemoveValue(services_dict, global_setup_v4_key);
global_v4_dict = CFDictionaryGetValue(info, global_setup_v4_key);
if (isA_CFDictionary(global_v4_dict) != NULL) { service_order = CFDictionaryGetValue(global_v4_dict, kSCPropNetServiceOrder); if (isA_CFArray(service_order) != NULL) { count = CFArrayGetCount(service_order); } }
active = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
range = CFRangeMake(0, 0);
for (i = 0; i < count ; i++) { int j; CFStringRef network_sig; CFStringRef service; CFStringRef service_id; CFDictionaryRef service_info; CFStringRef afs[2] = {kSCEntNetIPv4, kSCEntNetIPv6};
service_id = CFArrayGetValueAtIndex(service_order, i);
if (isA_CFString(service_id) == NULL) { continue; }
for (j = 0; j < 2; j++) { service = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainState, service_id, afs[j]);
service_info = CFDictionaryGetValue(services_dict, service);
/* Does this service have a signature? */ if (isA_CFDictionary(service_info) != NULL) { network_sig = CFDictionaryGetValue(service_info, kStoreKeyNetworkSignature); if (isA_CFString(network_sig) && !CFArrayContainsValue(active, range, network_sig)) { CFArrayAppendValue(active, network_sig); network_sig = NULL; range.length++; } CFDictionaryRemoveValue(services_dict, service); } CFRelease(service); } }
count = CFDictionaryGetCount(services_dict); if (count != 0) { if (count > KEYS_STATIC_COUNT) { values = (const void * *)malloc(sizeof(*values) * count); } else { values = values_static; } CFDictionaryGetKeysAndValues(services_dict, NULL, (const void * *)values); }
for (i = 0; i < count; i++) { CFStringRef network_sig; CFDictionaryRef service_dict = (CFDictionaryRef)values[i];
if (isA_CFDictionary(service_dict) == NULL) { continue; }
network_sig = CFDictionaryGetValue(service_dict, kStoreKeyNetworkSignature); /* Does this service have a signature? */ if (isA_CFString(network_sig) && !CFArrayContainsValue(active, range, network_sig)) { CFArrayAppendValue(active, network_sig); range.length++; network_sig = NULL; } } done: if (info != NULL) { CFRelease(info); } if (services_dict != NULL) { CFRelease(services_dict); } if (global_setup_v4_key != NULL) { CFRelease(global_setup_v4_key); } if (v4_service_pattern != NULL) { CFRelease(v4_service_pattern); } if (v6_service_pattern != NULL) { CFRelease(v6_service_pattern); } if (values != NULL && values != values_static) { free(values); } if (keys != NULL) { CFRelease(keys); } if (patterns != NULL) { CFRelease(patterns); } if (active != NULL && CFArrayGetCount(active) == 0) { CFRelease(active); active = NULL; } if (active == NULL) { _SCErrorSet(kSCStatusFailed); } return (active);}
CFStringRefSCNetworkSignatureCopyIdentifierForConnectedSocket(CFAllocatorRef alloc, int sock_fd){ CFStringRef addresses_key; int af; CFIndex count; int i; char if_name[IFNAMSIZ]; CFStringRef if_name_cf = NULL; conninfo_t * info = NULL; const void * * keys = NULL;#define KEYS_STATIC_COUNT 10 const void * keys_static[KEYS_STATIC_COUNT]; const void * local_ip_p; CFStringRef local_ip_str = NULL; CFStringRef ret_signature = NULL; CFDictionaryRef service_info = NULL; int status = kSCStatusFailed;
if (copyconninfo(sock_fd, SAE_CONNID_ANY, &info) != 0) { status = kSCStatusInvalidArgument; goto done; } if ((info->ci_flags & CIF_CONNECTED) == 0 || info->ci_src == NULL) { goto done; } af = info->ci_src->sa_family; switch (af) { case AF_INET: addresses_key = kSCPropNetIPv4Addresses; local_ip_p = &((struct sockaddr_in *) (void *)info->ci_src)->sin_addr; break; case AF_INET6: addresses_key = kSCPropNetIPv6Addresses; local_ip_p = &((struct sockaddr_in6 *) (void *)info->ci_src)->sin6_addr; break; default: status = kSCStatusInvalidArgument; goto done; }
/* search for service with matching IP address and interface name */ service_info = copy_services_for_address_family(alloc, af); if (service_info == NULL) { goto done; } local_ip_str = my_IPAddressToCFString(af, local_ip_p); if (local_ip_str == NULL) { goto done; } if (info->ci_ifindex != 0 && if_indextoname(info->ci_ifindex, if_name) != NULL) { if_name_cf = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII); } count = CFDictionaryGetCount(service_info); if (count > KEYS_STATIC_COUNT) { keys = (const void * *)malloc(sizeof(*keys) * count); } else { keys = keys_static; } CFDictionaryGetKeysAndValues(service_info, keys, NULL); for (i = 0; i < count; i++) { CFArrayRef addrs; CFRange range; CFStringRef signature; CFDictionaryRef value;
value = CFDictionaryGetValue(service_info, keys[i]); if (isA_CFDictionary(value) == NULL) { continue; } signature = CFDictionaryGetValue(value, kStoreKeyNetworkSignature); if (isA_CFString(signature) == NULL) { /* no signature */ continue; } if (if_name_cf != NULL) { CFStringRef confirmed_if; CFStringRef this_if;
this_if = CFDictionaryGetValue(value, kSCPropInterfaceName); if (isA_CFString(this_if) == NULL || !CFEqual(this_if, if_name_cf)) { /* no interface or it doesn't match */ continue; } confirmed_if = CFDictionaryGetValue(value, kSCPropConfirmedInterfaceName); if (isA_CFString(confirmed_if) != NULL && !CFEqual(confirmed_if, if_name_cf)) { /* confirmed interface doesn't match */ continue; } }
addrs = CFDictionaryGetValue(value, addresses_key); if (isA_CFArray(addrs) == NULL) { continue; } range = CFRangeMake(0, CFArrayGetCount(addrs)); if (CFArrayContainsValue(addrs, range, local_ip_str)) { ret_signature = CFRetain(signature); status = kSCStatusOK; break; } }
done: if (info != NULL) { freeconninfo(info); } if (if_name_cf != NULL) { CFRelease(if_name_cf); } if (local_ip_str != NULL) { CFRelease(local_ip_str); } if (keys != NULL && keys != keys_static) { free(keys); } if (service_info != NULL) { CFRelease(service_info); } if (status != kSCStatusOK) { _SCErrorSet(status); } return (ret_signature);}
#pragma mark -