+ // match SCNetworkInterfaceInfo
+ {
+ CFDictionaryRef known_info;
+ Boolean match;
+
+ known_info = _SCNetworkInterfaceCopyInterfaceInfo(known_if);
+ match = matchInterfaceInfo(known_info, match_context->match_info);
+ if (known_info != NULL) CFRelease(known_info);
+ if (!match) {
+ return;
+ }
+ }
+
+ // if requested, match [non-]builtin
+ if (match_context->match_builtin != NULL) {
+ CFBooleanRef known_builtin;
+
+ known_builtin = _SCNetworkInterfaceIsBuiltin(known_if) ? kCFBooleanTrue
+ : kCFBooleanFalse;
+ if (!_SC_CFEqual(known_builtin, match_context->match_builtin)) {
+ return;
+ }
+ }
+
+ // if we have a match
+ CFRelease(match_context->matches);
+ match_context->matches = NULL;
+
+ return;
+}
+
+/*
+ * lookupMatchingInterface
+ *
+ * Looks at the interfaces that have already been [or need to be] named with
+ * the goal of allowing a system using a single network interface/adaptor of
+ * a given type (vendor, model, ...) to not care about the specific adaptor
+ * that is used (i.e. swapping dongle's is OK). Once a system has had more
+ * than one interface/adaptor connected at the same time than we assume that
+ * the network configuration is being setup for multi-homing that should be
+ * maintained.
+ *
+ * If no matches are found or if more than one match is found, return NULL.
+ * If a single match is found, return the match.
+ */
+static CFDictionaryRef
+lookupMatchingInterface(SCNetworkInterfaceRef interface,
+ CFArrayRef db_list, // already named
+ CFArrayRef if_list, // to be named
+ CFIndex if_list_index,
+ CFBooleanRef builtin)
+{
+ CFStringRef if_type;
+ CFDictionaryRef match = NULL;
+ matchContext match_context;
+
+ if_type = SCNetworkInterfaceGetInterfaceType(interface);
+ if (if_type == NULL) {
+ return NULL;
+ }
+
+ match_context.match_type = if_type;
+ match_context.match_info = _SCNetworkInterfaceCopyInterfaceInfo(interface);
+ match_context.match_builtin = builtin;
+ match_context.matches = NULL;
+
+ // check for matches to already named interfaces
+ // ... and appends each match that we find to match_context.matches
+ if (db_list != NULL) {
+ CFArrayApplyFunction(db_list,
+ CFRangeMake(0, CFArrayGetCount(db_list)),
+ matchKnown,
+ &match_context);
+ }
+
+ // check for matches to to be named interfaces
+ // ... and CFReleases match_context.matches if we find another network
+ // interface of the same type that also needs to be named
+ if (if_list != NULL) {
+ CFIndex if_list_count;
+
+ if_list_count = CFArrayGetCount(if_list);
+ if (if_list_index < if_list_count) {
+ CFArrayApplyFunction(if_list,
+ CFRangeMake(if_list_index, if_list_count - if_list_index),
+ matchUnnamed,
+ &match_context);
+ }
+ }
+
+ // check if we have a single match
+ if (match_context.matches != NULL) {
+ if (CFArrayGetCount(match_context.matches) == 1) {
+ match = CFArrayGetValueAtIndex(match_context.matches, 0);
+ }
+ CFRelease(match_context.matches);
+ }
+
+ if (match != NULL) {
+ Boolean active = TRUE;
+ CFStringRef name;
+
+ name = CFDictionaryGetValue(match, CFSTR(kIOBSDNameKey));
+ if (isA_CFString(name)) {
+ int sock;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock != -1) {
+ struct ifreq ifr;
+
+ (void)_SC_cfstring_to_cstring(name, ifr.ifr_name, sizeof(ifr.ifr_name), kCFStringEncodingASCII);
+ if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
+ // if interface name not currently in-use
+ active = FALSE;
+ }
+ close(sock);