Boolean
SCVLANInterfaceRemove(SCVLANInterfaceRef vlan)
{
	CFStringRef			vlan_if;
	SCNetworkInterfacePrivateRef	interfacePrivate	= (SCNetworkInterfacePrivateRef)vlan;
	Boolean				ok;
	CFStringRef			path;

	if (!isA_SCVLANInterface(vlan)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	if (interfacePrivate->prefs == NULL) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	vlan_if = SCNetworkInterfaceGetBSDName(vlan);
	path    = CFStringCreateWithFormat(NULL,
					   NULL,
					   CFSTR("/%@/%@/%@"),
					   kSCPrefVirtualNetworkInterfaces,
					   kSCNetworkInterfaceTypeVLAN,
					   vlan_if);
	ok = SCPreferencesPathRemoveValue(interfacePrivate->prefs, path);
	CFRelease(path);

	return ok;
}
Ejemplo n.º 2
0
/*
 * Function: copy_present_interface
 * Purpose:
 *   Check the list of interfaces on the system, and find the one corresponding
 *   to the specified BSD name.
 */
STATIC SCNetworkInterfaceRef
copy_present_interface(CFStringRef if_name)
{
    int				count = 0;
    int				i;
    CFArrayRef			list;
    SCNetworkInterfaceRef	ret = NULL;

    list = SCNetworkInterfaceCopyAll();
    if (list != NULL) {
	count = CFArrayGetCount(list);
    }
    if (count == 0) {
	goto done;
    }
    for (i = 0; i < count; i++) {
	SCNetworkInterfaceRef	this_if;
	CFStringRef		this_if_name;

	this_if = (SCNetworkInterfaceRef)CFArrayGetValueAtIndex(list, i);
	this_if_name = SCNetworkInterfaceGetBSDName(this_if);
	if (this_if_name == NULL) {
	    continue;
	}
	if (CFEqual(if_name, this_if_name)) {
	    ret = this_if;
	    CFRetain(ret);
	    break;
	}
    }

 done:
    my_CFRelease(&list);
    return (ret);
}
Ejemplo n.º 3
0
/*
 * Function: copy_configured_interface_names
 *
 * Purpose:
 *   Return the BSD interface name of all configured interfaces.  If
 *   'entity' is non-NULL, also check that the interface has the specified
 *   extended configuration.
 */
STATIC CFArrayRef /* of CFStringRef */
copy_configured_interface_names(SCPreferencesRef prefs, CFStringRef entity_name)
{
    SCNetworkSetRef		current_set = NULL;
    int				count;
    int				i;
    CFMutableArrayRef		ret_names = NULL;
    CFRange			ret_names_range = { 0 , 0 };
    CFArrayRef			services = NULL;

    if (prefs == NULL) {
	goto done;
    }
    current_set = SCNetworkSetCopyCurrent(prefs);
    if (current_set == NULL) {
	goto done;
    }
    services = SCNetworkSetCopyServices(current_set);
    if (services == NULL) {
	goto done;
    }

    count = CFArrayGetCount(services);
    for (i = 0; i < count; i++) {
	CFStringRef		this_if_name;
	SCNetworkInterfaceRef	this_if;
	SCNetworkServiceRef	s;

	s = (SCNetworkServiceRef)CFArrayGetValueAtIndex(services, i);
	this_if = SCNetworkServiceGetInterface(s);
	if (this_if == NULL) {
	    continue;
	}
	if (entity_name != NULL
	    && (SCNetworkInterfaceGetExtendedConfiguration(this_if, entity_name)
		== NULL)) {
	    /* interface doesn't have specified entity */
	    continue;
	}
	this_if_name = SCNetworkInterfaceGetBSDName(this_if);
	if (this_if_name == NULL) {
	    continue;
	}
	if (ret_names == NULL
	    || CFArrayContainsValue(ret_names, ret_names_range,
				    this_if_name) == FALSE) {
	    if (ret_names == NULL) {
		ret_names = CFArrayCreateMutable(NULL, count, 
						 &kCFTypeArrayCallBacks);
	    }
	    CFArrayAppendValue(ret_names, this_if_name);
	    ret_names_range.length++;
	}
    }

 done:
    my_CFRelease(&current_set);
    my_CFRelease(&services);
    return (ret_names);
}
Ejemplo n.º 4
0
static CFArrayRef
updateServices(CFArrayRef services, SCNetworkInterfaceRef interface)
{
	CFStringRef		bsdName;
	CFIndex			i;
	CFIndex			n;
	CFMutableArrayRef	newServices;

	if (services == NULL) {
		return NULL;
	}

	bsdName = SCNetworkInterfaceGetBSDName(interface);

	newServices = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);

	n = CFArrayGetCount(services);
	for (i = 0; i < n; i++) {
		SCNetworkInterfaceRef		interface;
		CFStringRef			interfaceName;
		SCNetworkServiceRef		newService;
		SCNetworkServiceRef		service;
		CFStringRef			serviceID;
		SCNetworkServicePrivateRef	servicePrivate;

		service = CFArrayGetValueAtIndex(services, i);
		interface = SCNetworkServiceGetInterface(service);
		interfaceName = SCNetworkInterfaceGetBSDName(interface);
		if (!_SC_CFEqual(interfaceName, bsdName)) {
			// if not a match, retain
			CFArrayAppendValue(newServices, service);
			continue;
		}

		// if a match, update
		serviceID = SCNetworkServiceGetServiceID(service);
		servicePrivate = (SCNetworkServicePrivateRef)service;
		newService = SCNetworkServiceCopy(servicePrivate->prefs, serviceID);
		if (newService != NULL) {
			CFArrayAppendValue(newServices, newService);
			CFRelease(newService);
		}
	}

	return newServices;
}
Ejemplo n.º 5
0
vector<InterfaceInfo> OSXPlatform::interfaces()
{
  vector<InterfaceInfo> result;
  
  CFStringRef name = CFSTR("com.codebutler.firesheep.backend");
  SCPreferencesRef prefs = SCPreferencesCreate(NULL, name, NULL);
  
  SCNetworkSetRef set = SCNetworkSetCopyCurrent(prefs);
  CFArrayRef services = SCNetworkSetCopyServices(set);
  
  int arraySize = CFArrayGetCount(services);
  for (int i = 0; i < arraySize; i++) {
    SCNetworkServiceRef service = (SCNetworkServiceRef) CFArrayGetValueAtIndex(services, i);
    
    if (SCNetworkServiceGetEnabled(service)) {
      SCNetworkInterfaceRef iface = SCNetworkServiceGetInterface(service);
    
      CFStringRef serviceName = SCNetworkServiceGetName(service);
      char cServiceName[(CFStringGetLength(serviceName) * 4) + 1];
      CFStringGetCString(serviceName, cServiceName, sizeof(cServiceName), kCFStringEncodingUTF8);
    
      CFStringRef type = SCNetworkInterfaceGetInterfaceType(iface);
      if (CFStringCompare(type, CFSTR("Ethernet"), 0) == kCFCompareEqualTo ||
        CFStringCompare(type, CFSTR("IEEE80211"), 0) == kCFCompareEqualTo) {
        
        char cType[(CFStringGetLength(type) * 4) + 1];
        CFStringGetCString(type, cType, sizeof(cType), kCFStringEncodingUTF8);

        CFStringRef bsdName = SCNetworkInterfaceGetBSDName(iface);
        char cBsdName[(CFStringGetLength(bsdName) * 4) + 1];
        CFStringGetCString(bsdName, cBsdName, sizeof(cBsdName), kCFStringEncodingUTF8);
      
        InterfaceInfo info((string(cBsdName)), (string(cServiceName)), (string(cType)));          
        result.push_back(info);
      }
    }
  }
  
  CFRelease(services);
  CFRelease(set);
  CFRelease(prefs);
  
  return result; 
}
Ejemplo n.º 6
0
STATIC SCNetworkInterfaceRef
copy_configured_interface(SCPreferencesRef prefs, CFStringRef if_name)
{
    SCNetworkSetRef		current_set = NULL;
    int				count;
    int				i;
    SCNetworkInterfaceRef	ret_if = NULL;
    CFArrayRef			services = NULL;
    
    current_set = SCNetworkSetCopyCurrent(prefs);
    if (current_set == NULL) {
	goto done;
    }
    services = SCNetworkSetCopyServices(current_set);
    if (services == NULL) {
	goto done;
    }
    count = CFArrayGetCount(services);
    for (i = 0; i < count; i++) {
	CFStringRef		this_if_name;
	SCNetworkInterfaceRef	this_if;
	SCNetworkServiceRef	s;

	s = (SCNetworkServiceRef)CFArrayGetValueAtIndex(services, i);
	this_if = SCNetworkServiceGetInterface(s);
	if (this_if == NULL) {
	    continue;
	}
	this_if_name = SCNetworkInterfaceGetBSDName(this_if);
	if (this_if_name == NULL) {
	    continue;
	}
	if (CFEqual(this_if_name, if_name)) {
	    ret_if = this_if;
	    CFRetain(ret_if);
	    break;
	}
    }

 done:
    my_CFRelease(&current_set);
    my_CFRelease(&services);
    return (ret_if);
}
Boolean
_SCVLANInterfaceUpdateConfiguration(SCPreferencesRef prefs)
{
	CFArrayRef			active		= NULL;
	CFArrayRef			config		= NULL;
	CFMutableDictionaryRef		devices		= NULL;
	CFIndex				i;
	CFIndex				nActive;
	CFIndex				nConfig;
	Boolean				ok		= TRUE;
	int				s		= -1;

	if (prefs == NULL) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	/* configured VLANs */
	config = SCVLANInterfaceCopyAll(prefs);
	nConfig = (config != NULL) ? CFArrayGetCount(config) : 0;

	/* physical interfaces */
	devices = CFDictionaryCreateMutable(NULL,
					    0,
					    &kCFTypeDictionaryKeyCallBacks,
					    &kCFTypeDictionaryValueCallBacks);

	/* active VLANs */
	active  = _SCVLANInterfaceCopyActive();
	nActive = (active != NULL) ? CFArrayGetCount(active) : 0;

	/* remove any no-longer-configured VLAN interfaces */
	for (i = 0; i < nActive; i++) {
		SCVLANInterfaceRef	a_vlan;
		CFStringRef		a_vlan_if;
		CFIndex			j;
		Boolean			found	= FALSE;

		a_vlan    = CFArrayGetValueAtIndex(active, i);
		a_vlan_if = SCNetworkInterfaceGetBSDName(a_vlan);

		for (j = 0; j < nConfig; j++) {
			SCVLANInterfaceRef	c_vlan;
			CFStringRef		c_vlan_if;

			c_vlan    = CFArrayGetValueAtIndex(config, j);
			c_vlan_if = SCNetworkInterfaceGetBSDName(c_vlan);

			if (CFEqual(a_vlan_if, c_vlan_if)) {
				found = TRUE;
				break;
			}
		}

		if (!found) {
			// remove VLAN interface
			if (s == -1) {
				s = inet_dgram_socket();
				if (s == -1) {
					_SCErrorSet(errno);
					ok = FALSE;
					goto done;
				}
			}
			if (!__destroyInterface(s, a_vlan_if)) {
				ok = FALSE;
				_SCErrorSet(errno);
			}
		}
	}

	/* create (and update) configured VLAN interfaces */
	for (i = 0; i < nConfig; i++) {
		SCVLANInterfaceRef	c_vlan;
		CFStringRef		c_vlan_if;
		SCNetworkInterfaceRef	c_vlan_physical;
		Boolean			found		= FALSE;
		CFIndex			j;
		CFBooleanRef		supported;

		c_vlan          = CFArrayGetValueAtIndex(config, i);
		c_vlan_if       = SCNetworkInterfaceGetBSDName(c_vlan);
		c_vlan_physical = SCVLANInterfaceGetPhysicalInterface(c_vlan);

		if (c_vlan_physical == NULL) {
			continue;
		}
		// determine if the physical interface supports VLANs
		supported = CFDictionaryGetValue(devices, c_vlan_physical);
		if (supported == NULL) {
			SCNetworkInterfacePrivateRef	c_vlan_physicalPrivate	= (SCNetworkInterfacePrivateRef)c_vlan_physical;

			supported = c_vlan_physicalPrivate->supportsVLAN ? kCFBooleanTrue
									 : kCFBooleanFalse;
			CFDictionaryAddValue(devices, c_vlan_physical, supported);
		}

		for (j = 0; j < nActive; j++) {
			SCVLANInterfaceRef	a_vlan;
			CFStringRef		a_vlan_if;

			a_vlan    = CFArrayGetValueAtIndex(active, j);
			a_vlan_if = SCNetworkInterfaceGetBSDName(a_vlan);

			if (CFEqual(c_vlan_if, a_vlan_if)) {
				if (!CFEqual(c_vlan, a_vlan)) {
					// update VLAN interface
					if (s == -1) {
						s = inet_dgram_socket();
						if (s == -1) {
							_SCErrorSet(errno);
							ok = FALSE;
							goto done;
						}
					}

					if (!CFBooleanGetValue(supported)
					    || !__vlan_clear(s, c_vlan_if)
					    || !__vlan_set(s, c_vlan_if,
							   SCNetworkInterfaceGetBSDName(c_vlan_physical),
							   SCVLANInterfaceGetTag(c_vlan))) {
						// something went wrong, try to blow the VLAN away
						if (!CFBooleanGetValue(supported)) {
							_SCErrorSet(kSCStatusFailed);
						}
						(void)__destroyInterface(s, c_vlan_if);
						ok = FALSE;
					}
				}

				found = TRUE;
				break;
			}
		}

		if (!found && CFBooleanGetValue(supported)) {
			// if the physical interface supports VLANs, add new interface
			Boolean		created;

			if (s == -1) {
				s = inet_dgram_socket();
				if (s == -1) {
					_SCErrorSet(errno);
					ok = FALSE;
					goto done;
				}
			}

			created = __createInterface(s, c_vlan_if);
			if (!created
			    || !__vlan_set(s,
					   c_vlan_if,
					   SCNetworkInterfaceGetBSDName(c_vlan_physical),
					   SCVLANInterfaceGetTag(c_vlan))) {
				if (created) {
					// something went wrong, try to blow the VLAN away
					(void)__destroyInterface(s, c_vlan_if);
				} else {
					_SCErrorSet(errno);
				}
				ok = FALSE;
			}
		}

	}

    done :

	if (active)	CFRelease(active);
	if (config)	CFRelease(config);
	if (devices)	CFRelease(devices);
	if (s != -1)	(void) close(s);

	return ok;
}
Boolean
SCVLANInterfaceSetPhysicalInterfaceAndTag(SCVLANInterfaceRef vlan, SCNetworkInterfaceRef physical, CFNumberRef tag)
{
	SCNetworkInterfacePrivateRef	interfacePrivate;
	Boolean				ok			= TRUE;

	if (!isA_SCVLANInterface(vlan)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	if (!isA_SCNetworkInterface(physical)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	interfacePrivate = (SCNetworkInterfacePrivateRef)physical;
	if (!interfacePrivate->supportsVLAN) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	if (isA_CFNumber(tag)) {
		int	tag_val;

		CFNumberGetValue(tag, kCFNumberIntType, &tag_val);
		if ((tag_val < 1) || (tag_val > 4094)) {
			_SCErrorSet(kSCStatusInvalidArgument);
			return FALSE;
		}
	} else {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	interfacePrivate = (SCNetworkInterfacePrivateRef)vlan;
	if (interfacePrivate->prefs != NULL) {
		SCVLANInterfaceRef	config_vlan;
		CFDictionaryRef		dict;
		CFMutableDictionaryRef	newDict;
		CFStringRef		path;

		// make sure that physical interface and tag are not used
		config_vlan = findVLANInterfaceAndTag(interfacePrivate->prefs, physical, tag);
		if (config_vlan != NULL) {
			if (!CFEqual(vlan, config_vlan)) {
				CFRelease(config_vlan);
				_SCErrorSet(kSCStatusKeyExists);
				return FALSE;
			}
			CFRelease(config_vlan);
		}

		// set interface/tag in the stored preferences
		path = CFStringCreateWithFormat(NULL,
						NULL,
						CFSTR("/%@/%@/%@"),
						kSCPrefVirtualNetworkInterfaces,
						kSCNetworkInterfaceTypeVLAN,
						interfacePrivate->entity_device);
		dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
		if (!isA_CFDictionary(dict)) {
			// if the prefs are confused
			CFRelease(path);
			_SCErrorSet(kSCStatusFailed);
			return FALSE;
		}

		newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
		CFDictionarySetValue(newDict,
				     kSCPropVirtualNetworkInterfacesVLANInterface,
				     SCNetworkInterfaceGetBSDName(physical));
		CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesVLANTag, tag);
		if (!CFEqual(dict, newDict)) {
			ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
		}
		CFRelease(newDict);
		CFRelease(path);
	}

	if (ok) {
		SCNetworkInterfacePrivateRef	newInterface;
		CFTypeRef			save;

		// set physical interface
		newInterface = __SCNetworkInterfaceCreateCopy(NULL,
							      physical,
							      interfacePrivate->prefs,
							      interfacePrivate->serviceID);
		save = interfacePrivate->vlan.interface;
		interfacePrivate->vlan.interface = (SCNetworkInterfaceRef)newInterface;
		if (save != NULL) CFRelease(save);

		// set tag
		save = interfacePrivate->vlan.tag;
		interfacePrivate->vlan.tag = CFRetain(tag);
		if (save != NULL) CFRelease(save);
	}

	return ok;
}
static Boolean
_SCBondInterfaceSetMemberInterfaces(SCBondInterfaceRef bond, CFArrayRef members)
{
	CFIndex				i;
	SCNetworkInterfacePrivateRef	interfacePrivate	= (SCNetworkInterfacePrivateRef)bond;
	CFIndex				n;
	CFMutableArrayRef		newMembers;
	Boolean				ok			= TRUE;

	n = (members != NULL) ? CFArrayGetCount(members) : 0;

	// set member interfaces in the stored preferences
	if (interfacePrivate->prefs != NULL) {
		CFDictionaryRef		dict;
		CFMutableDictionaryRef	newDict;
		CFStringRef		path;

		path = CFStringCreateWithFormat(NULL,
						NULL,
						CFSTR("/%@/%@/%@"),
						kSCPrefVirtualNetworkInterfaces,
						kSCNetworkInterfaceTypeBond,
						interfacePrivate->entity_device);
		dict = SCPreferencesPathGetValue(interfacePrivate->prefs, path);
		if (!isA_CFDictionary(dict)) {
			// if the prefs are confused
			CFRelease(path);
			_SCErrorSet(kSCStatusFailed);
			return FALSE;
		}

		newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		for (i = 0; i < n; i++) {
			SCNetworkInterfaceRef	interface;
			CFStringRef		memberName;

			interface = CFArrayGetValueAtIndex(members, i);
			memberName = SCNetworkInterfaceGetBSDName(interface);
			CFArrayAppendValue(newMembers, memberName);
		}

		newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
		CFDictionarySetValue(newDict, kSCPropVirtualNetworkInterfacesBondInterfaces, newMembers);
		CFRelease(newMembers);
		if (!CFEqual(dict, newDict)) {
			ok = SCPreferencesPathSetValue(interfacePrivate->prefs, path, newDict);
		}
		CFRelease(newDict);
		CFRelease(path);
	}

	if (ok) {
		newMembers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
		for (i = 0; i < n; i++) {
			SCNetworkInterfaceRef		member;
			SCNetworkInterfacePrivateRef	newMember;

			member = CFArrayGetValueAtIndex(members, i);
			newMember = __SCNetworkInterfaceCreateCopy(NULL,
								   member,
								   interfacePrivate->prefs,
								   interfacePrivate->serviceID);
			CFArrayAppendValue(newMembers, newMember);
			CFRelease(newMember);
		}
		CFRelease(interfacePrivate->bond.interfaces);
		interfacePrivate->bond.interfaces = newMembers;
	}

	return ok;
}
Boolean
_SCBondInterfaceUpdateConfiguration(SCPreferencesRef prefs)
{
	CFArrayRef			active		= NULL;
	CFArrayRef			config		= NULL;
	CFIndex				i;
	CFIndex				nActive;
	CFIndex				nConfig;
	Boolean				ok		= TRUE;
	int				s		= -1;

	if (prefs == NULL) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return FALSE;
	}

	/* configured Bonds */
	config  = SCBondInterfaceCopyAll(prefs);
	nConfig = (config != NULL) ? CFArrayGetCount(config) : 0;

	/* active Bonds */
	active  = _SCBondInterfaceCopyActive();
	nActive = (active != NULL) ? CFArrayGetCount(active) : 0;

	/*
	 * remove any no-longer-configured bond interfaces and
	 * any devices associated with a bond that are no longer
	 * associated with a bond.
	 */
	for (i = 0; i < nActive; i++) {
		SCBondInterfaceRef	a_bond;
		CFStringRef		a_bond_if;
		CFIndex			j;
		Boolean			found	= FALSE;

		a_bond    = CFArrayGetValueAtIndex(active, i);
		a_bond_if = SCNetworkInterfaceGetBSDName(a_bond);

		for (j = 0; j < nConfig; j++) {
			SCBondInterfaceRef	c_bond;
			CFStringRef		c_bond_if;

			c_bond    = CFArrayGetValueAtIndex(config, j);
			c_bond_if = SCNetworkInterfaceGetBSDName(c_bond);

			if (CFEqual(a_bond_if, c_bond_if)) {
				CFIndex		a;
				CFArrayRef	a_bond_interfaces;
				CFIndex		a_count;
				CFArrayRef	c_bond_interfaces;
				CFIndex		c_count;

				c_bond_interfaces = SCBondInterfaceGetMemberInterfaces(c_bond);
				c_count           = (c_bond_interfaces != NULL) ? CFArrayGetCount(c_bond_interfaces) : 0;

				a_bond_interfaces = SCBondInterfaceGetMemberInterfaces(a_bond);
				a_count           = (a_bond_interfaces != NULL) ? CFArrayGetCount(a_bond_interfaces) : 0;

				for (a = 0; a < a_count; a++) {
					SCNetworkInterfaceRef	a_interface;
					CFStringRef		a_interface_if;

					a_interface = CFArrayGetValueAtIndex(a_bond_interfaces, a);
					if ((c_count == 0) ||
					    !CFArrayContainsValue(c_bond_interfaces,
								  CFRangeMake(0, c_count),
								  a_interface)) {
						/*
						 * if this device is no longer part
						 * of the bond.
						 */
						if (s == -1) {
							s = inet_dgram_socket();
							if (s == -1) {
								_SCErrorSet(errno);
								ok = FALSE;
								goto done;
							}
						}

						a_interface_if = SCNetworkInterfaceGetBSDName(a_interface);
						if (!__bond_remove_interface(s, a_bond_if, a_interface_if)) {
							ok = FALSE;
						}
					}
				}

				found = TRUE;
				break;
			}
		}

		if (!found) {
			/*
			 * if this interface is no longer configured
			 */
			if (s == -1) {
				s = inet_dgram_socket();
				if (s == -1) {
					_SCErrorSet(errno);
					ok = FALSE;
					goto done;
				}
			}

			if (!__destroyInterface(s, a_bond_if)) {
				_SCErrorSet(errno);
				ok = FALSE;
			}
		}
	}

	/*
	 * add any newly-configured bond interfaces and add any
	 * devices that should now be associated with the bond.
	 */
	for (i = 0; i < nConfig; i++) {
		CFNumberRef		c_bond_mode;
		SCBondInterfaceRef	c_bond;
		CFArrayRef		c_bond_interfaces;
		CFStringRef		c_bond_if;
		CFIndex			c_count;
		Boolean			found		= FALSE;
		CFIndex			j;

		c_bond            = CFArrayGetValueAtIndex(config, i);
		c_bond_if         = SCNetworkInterfaceGetBSDName(c_bond);
		c_bond_interfaces = SCBondInterfaceGetMemberInterfaces(c_bond);
		c_bond_mode       = SCBondInterfaceGetMode(c_bond);
		c_count           = (c_bond_interfaces != NULL) ? CFArrayGetCount(c_bond_interfaces) : 0;

		for (j = 0; j < nActive; j++) {
			SCBondInterfaceRef	a_bond;
			CFArrayRef		a_bond_interfaces;
			CFNumberRef		a_bond_mode;
			CFStringRef		a_bond_if;
			CFIndex			a_count;

			a_bond            = CFArrayGetValueAtIndex(active, j);
			a_bond_if         = SCNetworkInterfaceGetBSDName(a_bond);
			a_bond_interfaces = SCBondInterfaceGetMemberInterfaces(a_bond);
			a_bond_mode		  = SCBondInterfaceGetMode(a_bond);
			a_count           = (a_bond_interfaces != NULL) ? CFArrayGetCount(a_bond_interfaces) : 0;

			if (CFEqual(c_bond_if, a_bond_if)) {
				CFIndex	c;
				Boolean	if_list_change = FALSE;
				Boolean mode_change = FALSE;

				found = TRUE;

				if (!_SC_CFEqual(a_bond_mode, c_bond_mode)) {
					mode_change = TRUE;
				}

				if (!_SC_CFEqual(c_bond_interfaces, a_bond_interfaces)) {
					if_list_change = TRUE;
				}
				if (!mode_change && !if_list_change) {
					break;	// if no change
				}
				if (s == -1) {
					s = inet_dgram_socket();
					if (s == -1) {
						_SCErrorSet(errno);
						ok = FALSE;
						goto done;
					}
				}
				if (mode_change) {
					__bond_set_mode(s, a_bond_if, c_bond_mode);
				}
				if (!if_list_change) {
					break; // no if list changes
				}

				/*
				 * ensure that the first device of the bond matches, if
				 * not then we remove all current devices and add them
				 * back in the preferred order.
				 */
				if ((c_count > 0) &&
				    (a_count > 0) &&
				    !CFEqual(CFArrayGetValueAtIndex(c_bond_interfaces, 0),
					     CFArrayGetValueAtIndex(a_bond_interfaces, 0))) {
					CFIndex	a;

					for (a = 0; a < a_count; a++) {
						SCNetworkInterfaceRef	a_interface;
						CFStringRef		a_interface_if;

						a_interface = CFArrayGetValueAtIndex(a_bond_interfaces, a);
						if (!CFArrayContainsValue(c_bond_interfaces,
									 CFRangeMake(0, c_count),
									 a_interface)) {
							continue;	// if already removed
						}

						a_interface_if = SCNetworkInterfaceGetBSDName(a_interface);
						if (!__bond_remove_interface(s, a_bond_if, a_interface_if)) {
							ok = FALSE;
						}
					}

					a_count = 0;	// all active devices have been removed
				}

				/*
				 * add any devices which are not currently associated
				 * with the bond interface.
				 */
				for (c = 0; c < c_count; c++) {
					SCNetworkInterfaceRef		c_interface;
					SCNetworkInterfacePrivateRef	c_interfacePrivate;
					CFStringRef			c_interface_if;

					c_interface = CFArrayGetValueAtIndex(c_bond_interfaces, c);
					if ((a_count == 0) ||
					    !CFArrayContainsValue(a_bond_interfaces,
								  CFRangeMake(0, a_count),
								  c_interface)) {
						/*
						 * check if this member interface can be added to a bond.
						 */
						c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface;
						if (!c_interfacePrivate->supportsBond) {
							// if member not supported
							continue;
						}

						/*
						 * if this member interface is not currently part of the bond.
						 */
						c_interface_if = SCNetworkInterfaceGetBSDName(c_interface);
						if (!__bond_add_interface(s, c_bond_if, c_interface_if)) {
							// if member could not be added
							ok = FALSE;
						}
					}
				}

				break;
			}
		}

		if (!found) {
			CFIndex	c;

			if (s == -1) {
				s = inet_dgram_socket();
				if (s == -1) {
					_SCErrorSet(errno);
					ok = FALSE;
					goto done;
				}
			}

			/*
			 * establish the new bond interface.
			 */
			if (!__createInterface(s, c_bond_if)) {
				_SCErrorSet(errno);
				ok = FALSE;
				continue;
			}

			/* set the mode */
			__bond_set_mode(s, c_bond_if, c_bond_mode);

			/*
			 * add the member interfaces
			 */
			for (c = 0; c < c_count; c++) {
				SCNetworkInterfaceRef		c_interface;
				SCNetworkInterfacePrivateRef	c_interfacePrivate;
				CFStringRef			c_interface_if;

				c_interface = CFArrayGetValueAtIndex(c_bond_interfaces, c);
				c_interfacePrivate = (SCNetworkInterfacePrivateRef)c_interface;
				if (!c_interfacePrivate->supportsBond) {
					// if member not supported
					continue;
				}

				c_interface_if = SCNetworkInterfaceGetBSDName(c_interface);
				if (!__bond_add_interface(s, c_bond_if, c_interface_if)) {
					// if member could not be added
					ok = FALSE;
				}
			}
		}

	}

    done :

	if (active != NULL)	CFRelease(active);
	if (config != NULL)	CFRelease(config);
	if (s != -1)		(void) close(s);

	return ok;
}
SCBondStatusRef
SCBondInterfaceCopyStatus(SCBondInterfaceRef bond)
{
	int				bond_if_active;
	int				bond_if_status;
	CFIndex				i;
	struct if_bond_status_req	*ibsr_p		= NULL;
	char				if_name[IFNAMSIZ];
	CFIndex				n;
	CFNumberRef			num;
	int				s;
	struct if_bond_status		*scan_p;
	SCBondStatusRef			status		= NULL;
	CFMutableDictionaryRef		status_bond;
	CFMutableDictionaryRef		status_interfaces;

	if (!isA_SCBondInterface(bond)) {
		_SCErrorSet(kSCStatusInvalidArgument);
		return NULL;
	}

	s = inet_dgram_socket();
	if (s == -1) {
		_SCErrorSet(errno);
		goto done;
	}

	_SC_cfstring_to_cstring(SCNetworkInterfaceGetBSDName(bond),
				if_name,
				sizeof(if_name),
				kCFStringEncodingASCII);
	if (siocgifmedia(s, if_name, &bond_if_status, &bond_if_active) == -1) {
		_SCErrorSet(errno);
		switch (errno) {
			case EBUSY :
			case ENXIO :
				break;
			default :
				SCLog(TRUE, LOG_ERR,
				      CFSTR("siocgifmedia(%s) failed: %s"),
				      if_name,
				      strerror(errno));
		}
		goto done;
	}
	ibsr_p = if_bond_status_req_copy(s, if_name);
	if (ibsr_p == NULL) {
		_SCErrorSet(errno);
		goto done;
	}

	status_bond = CFDictionaryCreateMutable(NULL,
						0,
						&kCFTypeDictionaryKeyCallBacks,
						&kCFTypeDictionaryValueCallBacks);

	status_interfaces = CFDictionaryCreateMutable(NULL,
						      0,
						      &kCFTypeDictionaryKeyCallBacks,
						      &kCFTypeDictionaryValueCallBacks);
	n = ibsr_p->ibsr_total;
	for (i = 0, scan_p = (struct if_bond_status *)ibsr_p->ibsr_buffer; i < n; i++, scan_p++) {
		int				collecting	= 0;
		int				distributing	= 0;
		SCNetworkInterfaceRef		interface;
		CFStringRef			interface_name;
		struct if_bond_partner_state *	ps;
		CFMutableDictionaryRef		status_interface;
		int				status_val;

		ps = &scan_p->ibs_partner_state;

		if (lacp_actor_partner_state_in_sync(scan_p->ibs_state)) {
			/* we're in-sync */
			status_val = kSCBondStatusOK;
			if (lacp_actor_partner_state_in_sync(ps->ibps_state)) {
				/* partner is also in-sync */
				if (lacp_actor_partner_state_collecting(scan_p->ibs_state)
				    && lacp_actor_partner_state_distributing(ps->ibps_state)) {
					/* we're able to collect (receive) frames */
					collecting = 1;
				}
				if (lacp_actor_partner_state_distributing(scan_p->ibs_state)
				    && lacp_actor_partner_state_collecting(ps->ibps_state)) {
					/* we're able to distribute (transmit) frames */
					distributing = 1;
				}
			}
		} else {
			int			active = 0;
			int			status = 0;
			static lacp_system	zeroes = { {0, 0, 0, 0, 0, 0}};

			if (siocgifmedia(s, scan_p->ibs_if_name, &status, &active) == -1) {
				switch (errno) {
					case EBUSY :
					case ENXIO :
						break;
					default :
						SCLog(TRUE, LOG_ERR,
						      CFSTR("siocgifmedia(%s) failed: %s"),
						      if_name,
						      strerror(errno));
						break;
				}
			}
			if (((status & IFM_AVALID) == 0) ||
			    ((status & IFM_ACTIVE) == 0) ||
			    ((active & IFM_FDX   ) == 0)) {
				/* link down or not full-duplex */
				status_val = kSCBondStatusLinkInvalid;
			} else if ((ps->ibps_system_priority == 0) &&
				   (bcmp(&zeroes, &ps->ibps_system, sizeof(zeroes)) == 0)) {
				/* no one on the other end of the link */
				status_val = kSCBondStatusNoPartner;
			} else if (active != bond_if_active) {
				/* the link speed was different */
				status_val = kSCBondStatusLinkInvalid;
			} else {
				/* partner is not in the active group */
				status_val = kSCBondStatusNotInActiveGroup;
			}
		}

		// interface
		strlcpy(if_name, scan_p->ibs_if_name, sizeof(if_name));
		interface_name = CFStringCreateWithCString(NULL, if_name, kCFStringEncodingASCII);
		interface = _SCNetworkInterfaceCreateWithBSDName(NULL, interface_name,
								 kIncludeNoVirtualInterfaces);
		CFRelease(interface_name);

		// interface status
		status_interface = CFDictionaryCreateMutable(NULL,
							     0,
							     &kCFTypeDictionaryKeyCallBacks,
							     &kCFTypeDictionaryValueCallBacks);
		num = CFNumberCreate(NULL, kCFNumberIntType, &status_val);
		CFDictionarySetValue(status_interface, kSCBondStatusDeviceAggregationStatus, num);
		CFRelease(num);
		num = CFNumberCreate(NULL, kCFNumberIntType, &collecting);
		CFDictionarySetValue(status_interface, kSCBondStatusDeviceCollecting, num);
		CFRelease(num);
		num = CFNumberCreate(NULL, kCFNumberIntType, &distributing);
		CFDictionarySetValue(status_interface, kSCBondStatusDeviceDistributing, num);
		CFRelease(num);

		CFDictionarySetValue(status_interfaces, interface, status_interface);
		CFRelease(interface);
		CFRelease(status_interface);
	}

	status = __SCBondStatusCreatePrivate(NULL, bond, status_bond, status_interfaces);
	CFRelease(status_bond);
	CFRelease(status_interfaces);

    done:

	if (s != -1) {
		close(s);
	}
	if (ibsr_p != NULL) {
		free(ibsr_p);
	}
	return (SCBondStatusRef)status;
}
Ejemplo n.º 12
0
/*
 * Function: saveInterfaceEAPOLConfiguration
 * Purpose:
 *   Save the SCNetworkInterface EAPOL information for System and LoginWindow
 *   modes.
 *
 *   Iterate over the changed SCNetworkInterfaceRef list cfg->sc_changed_if,
 *   and for each interface, grab the EAPOL extended information from
 *   cfg->sc_prefs.    Then set the corresponding value in the new
 *   freshly created SCPreferencesRef.
 *
 *   All this done to avoid a writer getting Stale Object errors
 *   when it has its own SCPreferencesRef object that it manipulates while
 *   having an EAPOLClientConfigurationRef open.
 */
STATIC Boolean
saveInterfaceEAPOLConfiguration(EAPOLClientConfigurationRef cfg,
				Boolean * changed_p)
{
    AuthorizationExternalForm *	auth_ext_p;
    int				count;
    int				i;
    SCPreferencesRef		prefs = NULL;
    Boolean			ret = FALSE;

    *changed_p = FALSE;
    if (cfg->sc_changed_if == NULL) {
	return (TRUE);
    }
    auth_ext_p = EAPOLClientConfigurationGetAuthorizationExternalForm(cfg);
    if (auth_ext_p != NULL) {
	AuthorizationRef	auth;
	OSStatus		status;

	status = AuthorizationCreateFromExternalForm(auth_ext_p, &auth);
	if (status != errAuthorizationSuccess) {
	    EAPLOG(LOG_ERR,
		   "EAPOLClientConfiguration: can't allocate Authorization, %d",
		   (int)status);
	    goto done;
	}
	prefs = SCPreferencesCreateWithAuthorization(NULL,
						     kPrefsName, NULL,
						     auth);
	AuthorizationFree(auth, kAuthorizationFlagDefaults);
    }
    else {
	prefs = SCPreferencesCreate(NULL, kPrefsName, NULL);
    }
    count = CFArrayGetCount(cfg->sc_changed_if);
    for (i = 0; i < count; i++) {
	CFDictionaryRef		dict;
	CFStringRef		if_name;
	SCNetworkInterfaceRef	net_if;

	net_if = (SCNetworkInterfaceRef)
	    CFArrayGetValueAtIndex(cfg->sc_changed_if, i);
	if_name = SCNetworkInterfaceGetBSDName(net_if);
	if (if_name == NULL) {
	    /* should not happen */
	    EAPLOG(LOG_ERR, "EAPOLClientConfiguration: missing BSD name");
	    continue;
	}
	dict = SCNetworkInterfaceGetExtendedConfiguration(net_if, kEAPOL);

	/* find the same interface in the saving prefs */
	if (set_eapol_configuration(prefs, if_name, dict) == FALSE) {
	    continue;
	}
    }

    ret = SCPreferencesCommitChanges(prefs);
    if (ret == FALSE) {
	EAPLOG(LOG_NOTICE,
	       "EAPOLClientConfigurationSave SCPreferencesCommitChanges"
	       " failed %s", SCErrorString(SCError()));
	goto done;
    }
    SCPreferencesApplyChanges(prefs);
    *changed_p = TRUE;

 done:
    my_CFRelease(&cfg->sc_changed_if);
    my_CFRelease(&prefs);
    return (ret);
}
Ejemplo n.º 13
0
__private_extern__
void
select_service(int argc, char **argv)
{
	SCNetworkInterfaceRef	interface;
	SCNetworkServiceRef	service;
	CFStringRef		serviceName;

	service = _find_service(argv[0]);

	if (service == NULL) {
		return;
	}

	if (net_service != NULL) CFRelease(net_service);
	net_service = CFRetain(service);

	serviceName = SCNetworkServiceGetName(service);
	if (serviceName != NULL) {
		SCPrint(TRUE, stdout, CFSTR("service \"%@\" selected\n"), serviceName);
	} else {
		SCPrint(TRUE, stdout,
			CFSTR("service ID \"%@\" selected\n"),
			SCNetworkServiceGetServiceID(service));
	}

	interface = SCNetworkServiceGetInterface(service);
	if (interface != NULL) {
		CFStringRef	interfaceName;

		if (net_interface != NULL) CFRelease(net_interface);
		net_interface = CFRetain(interface);

		interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
		if (interfaceName == NULL) {
			interfaceName = SCNetworkInterfaceGetBSDName(interface);
		}
		if (interfaceName == NULL) {
			interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
		}

		SCPrint(TRUE, stdout,
			CFSTR("& interface \"%@\" selected\n"),
			interfaceName);
	} else {
		if (net_interface != NULL) {
			CFRelease(net_interface);
			net_interface = NULL;
			SCPrint(TRUE, stdout, CFSTR("& no interface selected\n"));
		}
	}

	if (protocols != NULL) {
		CFRelease(protocols);
		protocols = NULL;
	}

	if (net_protocol != NULL) {
		CFRelease(net_protocol);
		net_protocol = NULL;
		SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
	}

	return;
}
Ejemplo n.º 14
0
static SCNetworkServiceRef
_find_service(char *match)
{
	Boolean			allowIndex	= TRUE;
	CFIndex			i;
	CFIndex			n;
	CFStringRef		select_name	= NULL;
	SCNetworkServiceRef	selected	= NULL;

	if (services == NULL) {
		if (net_set == NULL) {
			SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
			return NULL;
		}

		services = SCNetworkSetCopyServices(net_set);
		if (services == NULL) {
			SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
			return NULL;
		}

		allowIndex = FALSE;
	}

	// try to select the service by its serviceID

	select_name = CFStringCreateWithCString(NULL, match, kCFStringEncodingUTF8);

	n = CFArrayGetCount(services);
	for (i = 0; i < n; i++) {
		SCNetworkServiceRef	service;
		CFStringRef		serviceID;

		service   = CFArrayGetValueAtIndex(services, i);
		serviceID = SCNetworkServiceGetServiceID(service);
		if (CFEqual(select_name, serviceID)) {
			selected = service;
			goto done;
		}
	}

	// try to select the service by its name

	for (i = 0; i < n; i++) {
		SCNetworkServiceRef	service;
		CFStringRef		serviceName;

		service     = CFArrayGetValueAtIndex(services, i);
		serviceName = SCNetworkServiceGetName(service);
		if ((serviceName != NULL) && CFEqual(select_name, serviceName)) {
			if (selected == NULL) {
				selected = service;
			} else {
				// if multiple services match
				selected = NULL;
				SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
				goto done;
			}
		}
	}

	if (selected != NULL) {
		goto done;
	}

	// try to select the service by its name (case insensitive)

	for (i = 0; i < n; i++) {
		SCNetworkServiceRef	service;
		CFStringRef		serviceName;

		service     = CFArrayGetValueAtIndex(services, i);
		serviceName = SCNetworkServiceGetName(service);
		if ((serviceName != NULL) &&
		    CFStringCompare(select_name,
				    serviceName,
				    kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
			if (selected == NULL) {
				selected = service;
			} else {
				// if multiple services match
				selected = NULL;
				SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
				goto done;
			}
		}
	}

	if (selected != NULL) {
		goto done;
	}

	// try to select the service by its [BSD] interface name

	for (i = 0; i < n; i++) {
		SCNetworkInterfaceRef	interface;
		CFStringRef		interfaceName	= NULL;
		SCNetworkServiceRef	service;

		service     = CFArrayGetValueAtIndex(services, i);

		interface = SCNetworkServiceGetInterface(service);
		while ((interface != NULL) && (interfaceName == NULL)) {
			interfaceName = SCNetworkInterfaceGetBSDName(interface);
			if (interfaceName == NULL) {
				interface = SCNetworkInterfaceGetInterface(interface);
			}
		}

		if (interfaceName == NULL) {
			continue;
		}

		if (CFStringCompare(select_name,
				    interfaceName,
				    kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
			if (selected == NULL) {
				selected = service;
			} else {
				// if multiple services match
				selected = NULL;
				SCPrint(TRUE, stdout, CFSTR("multiple services match\n"));
				goto done;
			}
		}
	}

	if (selected != NULL) {
		goto done;
	}

	// try to select the service by its index

	if (allowIndex) {
		char	*end;
		char	*str	= match;
		long	val;

		errno = 0;
		val = strtol(str, &end, 10);
		if ((*str != '\0') && (*end == '\0') && (errno == 0)) {
			if ((val > 0) && (val <= n)) {
				selected = CFArrayGetValueAtIndex(services, val - 1);
			}
		}
	}

	if (selected != NULL) {
		goto done;
	}

	SCPrint(TRUE, stdout, CFSTR("no match, which service?\n"));

    done :

	if (select_name != NULL) CFRelease(select_name);
	return selected;
}
Ejemplo n.º 15
0
__private_extern__
void
create_service(int argc, char **argv)
{
	SCNetworkInterfaceRef	interface;
	CFStringRef		interfaceName;
	Boolean			ok;
	SCNetworkServiceRef	service		= NULL;
	CFStringRef		serviceName;
	CFStringRef		setName;
	CFArrayRef		supported;

	if (prefs == NULL) {
		SCPrint(TRUE, stdout, CFSTR("network configuration not open\n"));
		return;
	}

	if (net_set == NULL) {
		SCPrint(TRUE, stdout, CFSTR("set not selected\n"));
		return;
	}

	if (argc < 1) {
		if (net_interface == NULL) {
			SCPrint(TRUE, stdout, CFSTR("no network interface selected\n"));
			return;
		}

		interface = net_interface;
	} else {
		int	nArgs;

		interface = _find_interface(argc, argv, &nArgs);
		argv += nArgs;
		argc -= nArgs;
	}

	if (interface == NULL) {
		return;
	}

	supported = SCNetworkInterfaceGetSupportedProtocolTypes(interface);
	if (supported == NULL) {
		SCPrint(TRUE, stdout, CFSTR("no network protocols are supported over this interface\n"));
		return;
	}

	service = SCNetworkServiceCreate(prefs, interface);
	if (service == NULL) {
		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
		goto done;
	}

	if ((argc > 0) && (strlen(argv[0]) > 0)) {
		Boolean         ok;

		serviceName = CFStringCreateWithCString(NULL, argv[0], kCFStringEncodingUTF8);
//		argv++;
//		argc--;

		ok = SCNetworkServiceSetName(service, serviceName);
		CFRelease(serviceName);
		if (!ok) {
			SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
			(void)SCNetworkServiceRemove(service);
			goto done;
		}
	}

	ok = SCNetworkServiceEstablishDefaultConfiguration(service);
	if (!ok) {
		SCPrint(TRUE, stdout, CFSTR("%s\n"), SCErrorString(SCError()));
		(void)SCNetworkServiceRemove(service);
		goto done;
	}

	ok = SCNetworkSetAddService(net_set, service);
	if (!ok) {
		SCPrint(TRUE, stdout, CFSTR("service not created: %s\n"), SCErrorString(SCError()));
		(void)SCNetworkServiceRemove(service);
		goto done;
	}

	_prefs_changed = TRUE;

	if (net_service != NULL) CFRelease(net_service);
	net_service = CFRetain(service);

	serviceName = SCNetworkServiceGetName(service);
	if (serviceName != NULL) {
		SCPrint(TRUE, stdout,
			CFSTR("service \"%@\" (%@) created and selected\n"),
			serviceName,
			SCNetworkServiceGetServiceID(service));
	} else {
		SCPrint(TRUE, stdout,
			CFSTR("service ID \"%@\" created and selected\n"),
			SCNetworkServiceGetServiceID(service));
	}

	setName = SCNetworkSetGetName(net_set);
	if (setName != NULL) {
		SCPrint(TRUE, stdout, CFSTR("& added to set \"%@\"\n"), setName);
	} else {
		SCPrint(TRUE, stdout, CFSTR("& added to set ID \"%@\"\n"),
			SCNetworkSetGetSetID(net_set));
	}

	if (net_interface != NULL) CFRelease(net_interface);
	net_interface = SCNetworkServiceGetInterface(net_service);
	if (net_interface != NULL) {
		CFRetain(net_interface);
	}

	interfaceName = SCNetworkInterfaceGetLocalizedDisplayName(interface);
	if (interfaceName == NULL) {
		interfaceName = SCNetworkInterfaceGetBSDName(interface);
	}
	if (interfaceName == NULL) {
		interfaceName = SCNetworkInterfaceGetInterfaceType(interface);
	}

	SCPrint(TRUE, stdout,
		CFSTR("& interface \"%@\" selected\n"),
		interfaceName);

	if (protocols != NULL) {
		CFRelease(protocols);
		protocols = NULL;
	}

	if (net_protocol != NULL) {
		CFRelease(net_protocol);
		net_protocol = NULL;
		SCPrint(TRUE, stdout, CFSTR("& no protocol selected\n"));
	}

	if (services != NULL) {
		CFRelease(services);
		services = NULL;
	}

    done :

	if (service != NULL) CFRelease(service);
	return;
}