Exemplo n.º 1
0
Arquivo: ifutil.c Projeto: aosm/bootp
PRIVATE_EXTERN int
interface_set_mtu(const char * ifname, int mtu)
{
    int ret = 0;
    int s = inet_dgram_socket();

    if (s < 0) {
	ret = errno;
    }
    else {
	if (siocsifmtu(s, ifname, mtu) < 0) {
	    ret = errno;
	    my_log(LOG_NOTICE, "siocsifmtu(%s, %d) failed, %s (%d)",
		   ifname, mtu, strerror(ret), ret);
	}
	close(s);
    }
    return (ret);

}
Exemplo n.º 2
0
Arquivo: ifutil.c Projeto: aosm/bootp
PRIVATE_EXTERN int
inet_detach_interface(const char * ifname)
{
    int ret = 0;
    int s = inet_dgram_socket();

    if (s < 0) {
	ret = errno;
	goto done;
    }
    if (siocprotodetach(s, ifname) < 0) {
	ret = errno;
	if (ret != ENXIO) {
	    my_log(LOG_ERR, "siocprotodetach(%s) failed, %s (%d)", 
		   ifname, strerror(errno), errno);
	}
    }
    close(s);

 done:
    return (ret);
}
Exemplo n.º 3
0
Arquivo: ifutil.c Projeto: aosm/bootp
PRIVATE_EXTERN int
inet_set_autoaddr(const char * ifname, int val)
{
    int 		s = inet_dgram_socket();
    int			ret = 0;

    if (s < 0) {
	ret = errno;
	my_log(LOG_ERR, 
	       "inet_set_autoaddr(%s, %d): socket() failed, %s (%d)",
	       ifname, val, strerror(errno), errno);
    }
    else {
	if (siocautoaddr(s, ifname, val) < 0) {
	    ret = errno;
	    if (ret != ENXIO) {
		my_log(LOG_ERR, "inet_set_autoaddr(%s, %d) failed, %s (%d)", 
		       ifname, val, strerror(errno), errno);
	    }
	}
	close(s);
    }
    return (ret);
}
Exemplo n.º 4
0
Arquivo: ifutil.c Projeto: aosm/bootp
PRIVATE_EXTERN int
inet_attach_interface(const char * ifname)
{
    int ret = 0;
    int s = inet_dgram_socket();

    if (s < 0) {
	ret = errno;
	goto done;
    }

    if (siocprotoattach(s, ifname) < 0) {
	ret = errno;
	if (ret != EEXIST && ret != ENXIO) {
	    my_log(LOG_DEBUG, "siocprotoattach(%s) failed, %s (%d)", 
		   ifname, strerror(errno), errno);
	}
    }
    (void)siocsifflags(s, ifname, IFF_UP);
    close(s);

 done:
    return (ret);
}
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;
}
CFArrayRef
_SCVLANInterfaceCopyActive(void)
{
	struct ifaddrs		*ifap;
	struct ifaddrs		*ifp;
	int			s;
	CFMutableArrayRef	vlans	= NULL;

	if (getifaddrs(&ifap) == -1) {
		SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
		_SCErrorSet(kSCStatusFailed);
		return NULL;
	}

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

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

	for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) {
		struct if_data		*if_data;
		struct ifreq		ifr;
		SCVLANInterfaceRef	vlan;
		CFStringRef		vlan_if;
		SCNetworkInterfaceRef	vlan_physical;
		CFStringRef		vlan_physical_if;
		CFNumberRef		vlan_tag;
		char			vlr_parent[IFNAMSIZ];
		int			vlr_tag;
		struct vlanreq		vreq;

		if_data = (struct if_data *)ifp->ifa_data;
		if (if_data == NULL
		    || ifp->ifa_addr->sa_family != AF_LINK
		    || if_data->ifi_type != IFT_L2VLAN) {
			continue;
		}

		bzero(&ifr, sizeof(ifr));
		bzero(&vreq, sizeof(vreq));
		strlcpy(ifr.ifr_name, ifp->ifa_name, sizeof(ifr.ifr_name));
		ifr.ifr_data = (caddr_t)&vreq;

		if (ioctl(s, SIOCGIFVLAN, (caddr_t)&ifr) == -1) {
			SCLog(TRUE, LOG_ERR, CFSTR("ioctl() failed: %s"), strerror(errno));
			CFRelease(vlans);
			vlans = NULL;
			_SCErrorSet(kSCStatusFailed);
			goto done;
		}

		// create the VLAN interface
		vlan_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII);
		vlan    = (SCVLANInterfaceRef)_SCVLANInterfaceCreatePrivate(NULL, vlan_if);
		assert(vlan != NULL);
		CFRelease(vlan_if);

		// set the physical interface and tag
		strlcpy(vlr_parent, vreq.vlr_parent, sizeof(vlr_parent));
		vlan_physical_if = CFStringCreateWithCString(NULL, vlr_parent, kCFStringEncodingASCII);
		vlan_physical = _SCNetworkInterfaceCreateWithBSDName(NULL, vlan_physical_if,
								     kIncludeBondInterfaces);
		assert(vlan_physical != NULL);
		CFRelease(vlan_physical_if);

		vlr_tag  = vreq.vlr_tag;
		vlan_tag = CFNumberCreate(NULL, kCFNumberIntType, &vlr_tag);
		assert(vlan_tag != NULL);

		SCVLANInterfaceSetPhysicalInterfaceAndTag(vlan, vlan_physical, vlan_tag);
		CFRelease(vlan_physical);
		CFRelease(vlan_tag);

		// add VLAN
		CFArrayAppendValue(vlans, vlan);
		CFRelease(vlan);
	}

    done :

	if (s != -1) {
		(void) close(s);
	}
	freeifaddrs(ifap);
	return vlans;
}
CFArrayRef
_SCBondInterfaceCopyActive(void)
{
	struct ifaddrs		*ifap;
	struct ifaddrs		*ifp;
	int			s;
	CFMutableArrayRef	bonds	= NULL;

	if (getifaddrs(&ifap) == -1) {
		_SCErrorSet(errno);
		SCLog(TRUE, LOG_ERR, CFSTR("getifaddrs() failed: %s"), strerror(errno));
		return NULL;
	}

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

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

	for (ifp = ifap; ifp != NULL; ifp = ifp->ifa_next) {
		SCBondInterfaceRef		bond;
		CFStringRef			bond_if;
		struct if_bond_status_req	*ibsr_p;
		struct if_data			*if_data;
		int				int_val;
		CFNumberRef			mode;
		CFMutableArrayRef		members		= NULL;

		if_data = (struct if_data *)ifp->ifa_data;
		if (if_data == NULL
		    || ifp->ifa_addr->sa_family != AF_LINK
		    || if_data->ifi_type != IFT_IEEE8023ADLAG) {
			continue;
		}

		ibsr_p = if_bond_status_req_copy(s, ifp->ifa_name);
		if (ibsr_p == NULL) {
			if (errno == EBUSY) {
				continue;
			}
			_SCErrorSet(errno);
			SCLog(TRUE, LOG_ERR,
			      CFSTR("if_bond_status_req_copy(%s) failed: %s"),
			      ifp->ifa_name,
			      strerror(errno));
			CFRelease(bonds);
			bonds = NULL;
			goto done;
		}

		// create the bond interface
		bond_if = CFStringCreateWithCString(NULL, ifp->ifa_name, kCFStringEncodingASCII);
		bond    = (SCBondInterfaceRef)_SCBondInterfaceCreatePrivate(NULL, bond_if);
		CFRelease(bond_if);

		// set the mode
		int_val = ibsr_p->ibsr_mode;
		mode = CFNumberCreate(NULL, kCFNumberIntType, &int_val);
		assert(mode != NULL);
		_SCBondInterfaceSetMode(bond, mode);
		CFRelease(mode);

		// add member interfaces
		if (ibsr_p->ibsr_total > 0) {
			int 			i;
			struct if_bond_status *	ibs_p;

			// iterate over each member interface
			ibs_p = (struct if_bond_status *)ibsr_p->ibsr_buffer;
			for (i = 0; i < ibsr_p->ibsr_total; i++) {
				CFStringRef	member;

				member = CFStringCreateWithCString(NULL, ibs_p[i].ibs_if_name, kCFStringEncodingASCII);
				add_interface(&members, member);
				CFRelease(member);
			}
		}
		free(ibsr_p);

		if (members != NULL) {
			_SCBondInterfaceSetMemberInterfaces(bond, members);
			CFRelease(members);
		}

		// add bond
		CFArrayAppendValue(bonds, bond);
		CFRelease(bond);
	}

    done :

	if (s != -1) {
		(void) close(s);
	}
	freeifaddrs(ifap);
	return bonds;
}
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;
}