static void
add_interface(CFMutableArrayRef *interfaces, CFStringRef if_name)
{
	SCNetworkInterfaceRef	interface;

	if (*interfaces == NULL) {
		*interfaces = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
	}

	interface = _SCNetworkInterfaceCreateWithBSDName(NULL, if_name,
							 kIncludeNoVirtualInterfaces);
	CFArrayAppendValue(*interfaces, interface);
	CFRelease(interface);
}
Exemplo n.º 2
0
static CFStringRef
copy_default_name(void)
{
	CFStringRef		model;
	size_t			n;
	CFMutableStringRef	str;

	// get HW model name
	model = _SC_hw_model(TRUE);
	if (model == NULL) {
		return NULL;
	}

	// start off with the [trunated] HW model
	str = CFStringCreateMutable(NULL, 0);
	CFStringAppend(str, model);

	// truncate as needed
	n = CFStringGetLength(str);
	if (n > (NETBIOS_NAME_LEN - 1)) {
		CFStringReplace(str,
				CFRangeMake(NETBIOS_NAME_LEN, n - (NETBIOS_NAME_LEN - 1)),
				CFSTR(""));
		n = NETBIOS_NAME_LEN - 1;
	}

	//
	// if there is room for at least one byte (two hex characters)
	// of the MAC address than append that to the NetBIOS name.
	//
	//    NETBIOS_NAME_LEN	max length
	//      -1		the last byte is reserved
	//      -3		"-XX"
	//
	if (n < (NETBIOS_NAME_LEN - 1 - 3)) {
		SCNetworkInterfaceRef	interface;

		interface = _SCNetworkInterfaceCreateWithBSDName(NULL, CFSTR("en0"),
								 kIncludeNoVirtualInterfaces);
		if (interface != NULL) {
			CFMutableStringRef	en0_MAC;

			en0_MAC = (CFMutableStringRef)SCNetworkInterfaceGetHardwareAddressString(interface);
			if (en0_MAC != NULL) {
				CFIndex	en0_MAC_len;

				// remove ":" characters from MAC address string
				en0_MAC = CFStringCreateMutableCopy(NULL, 0, en0_MAC);
				CFStringFindAndReplace(en0_MAC,
						       CFSTR(":"),
						       CFSTR(""),
						       CFRangeMake(0, CFStringGetLength(en0_MAC)),
						       0);

				//
				// compute how may bytes (characters) to append
				//    ... and limit that number to 6
				//
				//    NETBIOS_NAME_LEN	max length
				//      -1		the last byte is reserved
				//	-n		"iMac"
				//      -1		"-"
				//
				n = ((NETBIOS_NAME_LEN - 1 - n - 1) / 2) * 2;
				if (n > 6) {
					n = 6;
				}

				// remove what we don't want
				en0_MAC_len = CFStringGetLength(en0_MAC);
				if (en0_MAC_len > n) {
					CFStringDelete(en0_MAC, CFRangeMake(0, en0_MAC_len - n));
				}

				// append
				CFStringAppendFormat(str, NULL, CFSTR("-%@"), en0_MAC);
				CFRelease(en0_MAC);
			}

			CFRelease(interface);
		}
	}

	CFStringUppercase(str, NULL);
	return str;
}
static void
add_configured_interface(const void *key, const void *value, void *context)
{
	SCNetworkInterfacePrivateRef	interfacePrivate;
	addContextRef			myContext	= (addContextRef)context;
	SCVLANInterfaceRef		vlan;
	CFStringRef			vlan_if		= (CFStringRef)key;
	CFDictionaryRef			vlan_info	= (CFDictionaryRef)value;
	CFStringRef			vlan_name;
	CFDictionaryRef			vlan_options;
	SCNetworkInterfaceRef		vlan_physical;
	CFStringRef			vlan_physical_if;
	CFNumberRef			vlan_tag;

	vlan_physical_if = CFDictionaryGetValue(vlan_info, kSCPropVirtualNetworkInterfacesVLANInterface);
	if (!isA_CFString(vlan_physical_if)) {
		// if prefs are confused
		return;
	}

	vlan_tag = CFDictionaryGetValue(vlan_info, kSCPropVirtualNetworkInterfacesVLANTag);
	if (!isA_CFNumber(vlan_tag)) {
		// if prefs are confused
		return;
	}

	// create the VLAN interface
	vlan = (SCVLANInterfaceRef)_SCVLANInterfaceCreatePrivate(NULL, vlan_if);
	assert(vlan != NULL);

	// set physical interface and tag
	vlan_physical = _SCNetworkInterfaceCreateWithBSDName(NULL, vlan_physical_if,
							     kIncludeBondInterfaces);
	assert(vlan_physical != NULL);

	// since we KNOW that the physical interface supported VLANs when
	// it was first established it's OK to force that state here ...
	// and this is needed for the case when the interface (e.g. a
	// dongle) is not currently attached to the system
	interfacePrivate = (SCNetworkInterfacePrivateRef)vlan_physical;
	interfacePrivate->supportsVLAN = TRUE;

	// and now we associate the physical interface and tag
	SCVLANInterfaceSetPhysicalInterfaceAndTag(vlan, vlan_physical, vlan_tag);
	CFRelease(vlan_physical);

	// set display name
	vlan_name = CFDictionaryGetValue(vlan_info, kSCPropUserDefinedName);
	if (isA_CFString(vlan_name)) {
		SCVLANInterfaceSetLocalizedDisplayName(vlan, vlan_name);
	}

	// set options
	vlan_options = CFDictionaryGetValue(vlan_info, kSCPropVirtualNetworkInterfacesVLANOptions);
	if (isA_CFDictionary(vlan_options)) {
		SCVLANInterfaceSetOptions(vlan, vlan_options);
	}

	// estabish link to the stored configuration
	interfacePrivate = (SCNetworkInterfacePrivateRef)vlan;
	interfacePrivate->prefs = CFRetain(myContext->prefs);

	CFArrayAppendValue(myContext->vlans, vlan);
	CFRelease(vlan);

	return;
}
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;
}
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;
}