int checkVPNInterfaceOrServiceBlocked (const char *location, char *interface_buf) { // check to see if interface is captive: if so, bail if the interface is not ready. if (check_interface_captive_and_not_ready(gDynamicStore, interface_buf)) { // TODO: perhaps we should wait for a few seconds? return true; } // return 1, if this is a delete event, and; // TODO: add support for IPv6 <rdar://problem/5920237> // walk Setup:/Network/Service/* and check if there are service entries referencing this interface. e.g. Setup:/Network/Service/44DB8790-0177-4F17-8D4E-37F9413D1D87/Interface:DeviceName == interface, other_serv_found = 1 // Setup:/Network/Interface/"interface"/AirPort:'PowerEnable' == 0 || Setup:/Network/Interface/"interface"/IPv4 is missing, interf_down = 1 if (gDynamicStore) { CFStringRef interf_key; CFMutableArrayRef interf_keys; CFStringRef pattern; CFMutableArrayRef patterns; CFDictionaryRef dict = NULL; CFIndex i; const void * keys_q[128]; const void ** keys = keys_q; const void * values_q[128]; const void ** values = values_q; CFIndex n; CFStringRef vpn_if; int other_serv_found = 0, interf_down = 0; vpn_if = CFStringCreateWithCStringNoCopy(NULL, interface_buf, kCFStringEncodingASCII, kCFAllocatorNull); if (!vpn_if) { // if we could not initialize interface CFString syslog(LOG_NOTICE, "%s: failed to initialize interface CFString", location); goto done; } interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); // get Setup:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainSetup, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get State:/Network/Interface/<vpn_if>/Airport interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, kSCDynamicStoreDomainState, vpn_if, kSCEntNetAirPort); CFArrayAppendValue(interf_keys, interf_key); CFRelease(interf_key); // get Setup:/Network/Service/*/Interface pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetInterface); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); // get Setup:/Network/Service/*/IPv4 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, kSCDynamicStoreDomainSetup, kSCCompAnyRegex, kSCEntNetIPv4); CFArrayAppendValue(patterns, pattern); CFRelease(pattern); dict = SCDynamicStoreCopyMultiple(gDynamicStore, interf_keys, patterns); CFRelease(interf_keys); CFRelease(patterns); if (!dict) { // if we could not access the SCDynamicStore syslog(LOG_NOTICE, "%s: failed to initialize SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } // look for the service which matches the provided prefixes n = CFDictionaryGetCount(dict); if (n <= 0) { syslog(LOG_NOTICE, "%s: empty SCDynamicStore dictionary", location); CFRelease(vpn_if); goto done; } if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); } CFDictionaryGetKeysAndValues(dict, keys, values); for (i=0; i < n; i++) { CFStringRef s_key = (CFStringRef)keys[i]; CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; CFStringRef s_if; if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { continue; } if (CFStringHasSuffix(s_key, kSCEntNetInterface)) { // is a Service Interface entity s_if = CFDictionaryGetValue(s_dict, kSCPropNetInterfaceDeviceName); if (isA_CFString(s_if) && CFEqual(vpn_if, s_if)) { CFArrayRef components; CFStringRef serviceIDRef = NULL, serviceKey = NULL; other_serv_found = 1; // extract service ID components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); if (CFArrayGetCount(components) > 3) { serviceIDRef = CFArrayGetValueAtIndex(components, 3); //if (new key) Setup:/Network/Service/service_id/IPv4 is missing, then interf_down = 1 serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetIPv4); if (!serviceKey || !CFDictionaryGetValue(dict, serviceKey)) { syslog(LOG_NOTICE, "%s: detected disabled IPv4 Config", location); interf_down = 1; } if (serviceKey) CFRelease(serviceKey); } if (components) CFRelease(components); if (interf_down) break; } continue; } else if (CFStringHasSuffix(s_key, kSCEntNetAirPort)) { // Interface/<vpn_if>/Airport entity if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainSetup)) { CFBooleanRef powerEnable = CFDictionaryGetValue(s_dict, kSCPropNetAirPortPowerEnabled); if (isA_CFBoolean(powerEnable) && CFEqual(powerEnable, kCFBooleanFalse)) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerEnable == FALSE", location); interf_down = 1; break; } } else if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainState)) { UInt16 temp; CFNumberRef airStatus = CFDictionaryGetValue(s_dict, CFSTR("Power Status")); if (isA_CFNumber(airStatus) && CFNumberGetValue(airStatus, kCFNumberShortType, &temp)) { if (temp ==0) { syslog(LOG_NOTICE, "%s: detected AirPort, PowerStatus == 0", location); } } } continue; } } if (vpn_if) CFRelease(vpn_if); if (keys != keys_q) { CFAllocatorDeallocate(NULL, keys); CFAllocatorDeallocate(NULL, values); } done : if (dict) CFRelease(dict); return (other_serv_found == 0 || interf_down == 1); } return 0; }
/* * Function: DHCPLeaseCreateWithDictionary * Purpose: * Instantiate a new DHCPLease structure corresponding to the given * dictionary. Validates that required properties are present, * returns NULL if those checks fail. */ static DHCPLeaseRef DHCPLeaseCreateWithDictionary(CFDictionaryRef dict, bool is_wifi) { CFDataRef hwaddr_data; dhcp_lease_time_t lease_time; DHCPLeaseRef lease_p; CFDataRef pkt_data; CFRange pkt_data_range; struct in_addr * router_p; CFStringRef ssid = NULL; CFDateRef start_date; dhcp_lease_time_t t1_time; dhcp_lease_time_t t2_time; /* get the lease start time */ start_date = CFDictionaryGetValue(dict, kLeaseStartDate); if (isA_CFDate(start_date) == NULL) { goto failed; } /* get the packet data */ pkt_data = CFDictionaryGetValue(dict, kPacketData); if (isA_CFData(pkt_data) == NULL) { goto failed; } /* if Wi-Fi, get the SSID */ if (is_wifi) { ssid = CFDictionaryGetValue(dict, kSSID); if (isA_CFString(ssid) == NULL) { goto failed; } } pkt_data_range.location = 0; pkt_data_range.length = CFDataGetLength(pkt_data); if (pkt_data_range.length < sizeof(struct dhcp)) { goto failed; } lease_p = (DHCPLeaseRef) malloc(offsetof(DHCPLease, pkt) + pkt_data_range.length); bzero(lease_p, offsetof(DHCPLease, pkt)); /* copy the packet data */ CFDataGetBytes(pkt_data, pkt_data_range, lease_p->pkt); lease_p->pkt_length = pkt_data_range.length; /* get the lease information and router IP address */ lease_p->lease_start = (absolute_time_t)CFDateGetAbsoluteTime(start_date); { /* parse/retrieve options */ dhcpol_t options; (void)dhcpol_parse_packet(&options, (void *)lease_p->pkt, pkt_data_range.length, NULL); dhcp_get_lease_from_options(&options, &lease_time, &t1_time, &t2_time); router_p = dhcp_get_router_from_options(&options, lease_p->our_ip); dhcpol_free(&options); } lease_p->lease_length = lease_time; /* get the IP address */ /* ALIGN: lease_p->pkt is aligned, cast ok. */ lease_p->our_ip = ((struct dhcp *)(void *)lease_p->pkt)->dp_yiaddr; /* get the router information */ if (router_p != NULL) { CFRange hwaddr_range; lease_p->router_ip = *router_p; /* get the router hardware address */ hwaddr_data = CFDictionaryGetValue(dict, kRouterHardwareAddress); hwaddr_range.length = 0; if (isA_CFData(hwaddr_data) != NULL) { hwaddr_range.length = CFDataGetLength(hwaddr_data); } if (hwaddr_range.length > 0) { hwaddr_range.location = 0; if (hwaddr_range.length > sizeof(lease_p->router_hwaddr)) { hwaddr_range.length = sizeof(lease_p->router_hwaddr); } lease_p->router_hwaddr_length = hwaddr_range.length; CFDataGetBytes(hwaddr_data, hwaddr_range, lease_p->router_hwaddr); } } if (ssid != NULL) { CFRetain(ssid); lease_p->ssid = ssid; } return (lease_p); failed: return (NULL); }