示例#1
0
	/**
	 * Derive the multicast group used for address resolution (ARP/NDP) for an IP
	 *
	 * @param ip IP address (port field is ignored)
	 * @return Multicat group for ARP/NDP
	 */
	static inline MulticastGroup deriveMulticastGroupForAddressResolution(const InetAddress &ip)
		throw()
	{
		if (ip.isV4()) {
			// IPv4 wants braodcast MACs, so we shove the V4 address itself into
			// the Multicast Group ADI field. Making V4 ARP work is basically why
			// ADI was added, as well as handling other things that want mindless
			// Ethernet broadcast to all.
			return MulticastGroup(MAC((unsigned char)0xff),Utils::ntoh(*((const uint32_t *)ip.rawIpData())));
		} else if (ip.isV6()) {
			// IPv6 is better designed in this respect. We can compute the IPv6
			// multicast address directly from the IP address, and it gives us
			// 24 bits of uniqueness. Collisions aren't likely to be common enough
			// to care about.
			const unsigned char *a = (const unsigned char *)ip.rawIpData();
			MAC m;
			m.data[0] = 0x33;
			m.data[1] = 0x33;
			m.data[2] = 0xff;
			m.data[3] = a[13];
			m.data[4] = a[14];
			m.data[5] = a[15];
			return MulticastGroup(m,0);
		}
		return MulticastGroup();
	}
const NetworkConfig::MulticastRate &NetworkConfig::multicastRate(const MulticastGroup &mg) const
	throw()
{
	std::map<MulticastGroup,MulticastRate>::const_iterator r(_multicastRates.find(mg));
	if (r == _multicastRates.end()) {
		r = _multicastRates.find(MulticastGroup()); // zero MG signifies network's default rate
		if (r == _multicastRates.end())
			return DEFAULT_MULTICAST_RATE; // neither specific nor default found in network config
	}
	return r->second;
}
void BSDEthernetTap::scanMulticastGroups(std::vector<MulticastGroup> &added,std::vector<MulticastGroup> &removed)
{
	std::vector<MulticastGroup> newGroups;

	struct ifmaddrs *ifmap = (struct ifmaddrs *)0;
	if (!getifmaddrs(&ifmap)) {
		struct ifmaddrs *p = ifmap;
		while (p) {
			if (p->ifma_addr->sa_family == AF_LINK) {
				struct sockaddr_dl *in = (struct sockaddr_dl *)p->ifma_name;
				struct sockaddr_dl *la = (struct sockaddr_dl *)p->ifma_addr;
				if ((la->sdl_alen == 6)&&(in->sdl_nlen <= _dev.length())&&(!memcmp(_dev.data(),in->sdl_data,in->sdl_nlen)))
					newGroups.push_back(MulticastGroup(MAC(la->sdl_data + la->sdl_nlen,6),0));
			}
			p = p->ifma_next;
		}
		freeifmaddrs(ifmap);
	}

	std::vector<InetAddress> allIps(ips());
	for(std::vector<InetAddress>::iterator ip(allIps.begin());ip!=allIps.end();++ip)
		newGroups.push_back(MulticastGroup::deriveMulticastGroupForAddressResolution(*ip));

	std::sort(newGroups.begin(),newGroups.end());
	std::unique(newGroups.begin(),newGroups.end());

	for(std::vector<MulticastGroup>::iterator m(newGroups.begin());m!=newGroups.end();++m) {
		if (!std::binary_search(_multicastGroups.begin(),_multicastGroups.end(),*m))
			added.push_back(*m);
	}
	for(std::vector<MulticastGroup>::iterator m(_multicastGroups.begin());m!=_multicastGroups.end();++m) {
		if (!std::binary_search(newGroups.begin(),newGroups.end(),*m))
			removed.push_back(*m);
	}

	_multicastGroups.swap(newGroups);
}
void NetworkConfig::_fromDictionary(const Dictionary &d)
{
	static const std::string zero("0");
	static const std::string one("1");

	// NOTE: d.get(name) throws if not found, d.get(name,default) returns default

	memset(_etWhitelist,0,sizeof(_etWhitelist));
	std::vector<std::string> ets(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES).c_str(),",","",""));
	for(std::vector<std::string>::const_iterator et(ets.begin());et!=ets.end();++et) {
		unsigned int tmp = Utils::hexStrToUInt(et->c_str()) & 0xffff;
		_etWhitelist[tmp >> 3] |= (1 << (tmp & 7));
	}

	_nwid = Utils::hexStrToU64(d.get(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID).c_str());
	if (!_nwid)
		throw std::invalid_argument("configuration contains zero network ID");
	_timestamp = Utils::hexStrToU64(d.get(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP).c_str());
	_issuedTo = Address(d.get(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO));
	_multicastPrefixBits = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_PREFIX_BITS,zero).c_str());
	_multicastDepth = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_DEPTH,zero).c_str());
	_allowPassiveBridging = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING,zero).c_str()) != 0);
	_private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,one).c_str()) != 0);
	_enableBroadcast = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST,one).c_str()) != 0);
	_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
	_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());

	if (!_multicastPrefixBits)
		_multicastPrefixBits = ZT_DEFAULT_MULTICAST_PREFIX_BITS;
	if (!_multicastDepth)
		_multicastDepth = ZT_DEFAULT_MULTICAST_DEPTH;

	std::string ipAddrs(d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC,std::string()));
	std::string v6s(d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC,std::string()));
	if (v6s.length()) {
		if (ipAddrs.length())
			ipAddrs.push_back(',');
		ipAddrs.append(v6s);
	}
	std::vector<std::string> ipAddrs2(Utils::split(ipAddrs.c_str(),",","",""));
	for(std::vector<std::string>::const_iterator ipstr(ipAddrs2.begin());ipstr!=ipAddrs2.end();++ipstr) {
		InetAddress addr(*ipstr);
		switch(addr.type()) {
			case InetAddress::TYPE_IPV4:
				if ((!addr.netmaskBits())||(addr.netmaskBits() > 32))
					throw std::invalid_argument("static IP address fields contain one or more invalid IP/netmask entries");
				break;
			case InetAddress::TYPE_IPV6:
				if ((!addr.netmaskBits())||(addr.netmaskBits() > 128))
					throw std::invalid_argument("static IP address fields contain one or more invalid IP/netmask entries");
				break;
			default:
				throw std::invalid_argument("static IP address fields contain one or more invalid IP/netmask entries");
		}
		_staticIps.insert(addr);
	}

	std::vector<std::string> ab(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","",""));
	for(std::vector<std::string>::const_iterator a(ab.begin());a!=ab.end();++a) {
		if (a->length() == ZT_ADDRESS_LENGTH_HEX) {
			Address tmp(*a);
			if (!tmp.isReserved())
				_activeBridges.insert(tmp);
		}
	}

	Dictionary mr(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES,std::string()));
	for(Dictionary::const_iterator i(mr.begin());i!=mr.end();++i) {
		std::vector<std::string> params(Utils::split(i->second.c_str(),",","",""));
		if (params.size() >= 3)
			_multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str()));
	}

	_com.fromString(d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP,std::string()));
}
示例#5
0
void Multicaster::bringCloser(uint64_t nwid,const Address &a)
{
	Mutex::Lock _l(_lock);

	std::map< uint64_t,_NetInfo >::iterator n(_nets.find(nwid));
	if (n == _nets.end())
		return;

	/* _subscriptions contains pairs of <Address,MulticastGroup>, so we can
	 * easily iterate through all subscriptions for a given address by
	 * starting with the default all-zero MulticastGroup() as lower bound
	 * and stopping when we're not looking at the right address anymore.
	 * Then we can look up _proximity and rapidly splice() the list using
	 * the saved iterator in _SubInfo. */

	std::map< _Subscription,_SubInfo >::iterator s(n->second.subscriptions.lower_bound(_Subscription(a,MulticastGroup())));
	while ((s != n->second.subscriptions.end())&&(s->first.first == a)) {
		std::map< MulticastGroup,std::list< Address > >::iterator p(n->second.proximity.find(s->first.second));
		if (s->second.proximitySlot != p->second.begin())
			p->second.splice(p->second.begin(),p->second,s->second.proximitySlot);
		++s;
	}
}
示例#6
0
void NetworkConfig::_fromDictionary(const Dictionary &d)
{
	static const std::string zero("0");
	static const std::string one("1");

	// NOTE: d.get(name) throws if not found, d.get(name,default) returns default

	_nwid = Utils::hexStrToU64(d.get(ZT_NETWORKCONFIG_DICT_KEY_NETWORK_ID).c_str());
	if (!_nwid)
		throw std::invalid_argument("configuration contains zero network ID");

	_timestamp = Utils::hexStrToU64(d.get(ZT_NETWORKCONFIG_DICT_KEY_TIMESTAMP).c_str());
	_revision = Utils::hexStrToU64(d.get(ZT_NETWORKCONFIG_DICT_KEY_REVISION,"1").c_str()); // older controllers don't send this, so default to 1

	memset(_etWhitelist,0,sizeof(_etWhitelist));
	std::vector<std::string> ets(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ALLOWED_ETHERNET_TYPES).c_str(),",","",""));
	for(std::vector<std::string>::const_iterator et(ets.begin());et!=ets.end();++et) {
		unsigned int tmp = Utils::hexStrToUInt(et->c_str()) & 0xffff;
		_etWhitelist[tmp >> 3] |= (1 << (tmp & 7));
	}

	_issuedTo = Address(d.get(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO));
	_multicastLimit = Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_LIMIT,zero).c_str());
	if (_multicastLimit == 0) _multicastLimit = ZT_MULTICAST_DEFAULT_LIMIT;
	_allowPassiveBridging = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ALLOW_PASSIVE_BRIDGING,zero).c_str()) != 0);
	_private = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_PRIVATE,one).c_str()) != 0);
	_enableBroadcast = (Utils::hexStrToUInt(d.get(ZT_NETWORKCONFIG_DICT_KEY_ENABLE_BROADCAST,one).c_str()) != 0);
	_name = d.get(ZT_NETWORKCONFIG_DICT_KEY_NAME);
	if (_name.length() > ZT1_MAX_NETWORK_SHORT_NAME_LENGTH)
		throw std::invalid_argument("network short name too long (max: 255 characters)");
	_description = d.get(ZT_NETWORKCONFIG_DICT_KEY_DESC,std::string());

	// In dictionary IPs are split into V4 and V6 addresses, but we don't really
	// need that so merge them here.
	std::string ipAddrs(d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV4_STATIC,std::string()));
	{
		std::string v6s(d.get(ZT_NETWORKCONFIG_DICT_KEY_IPV6_STATIC,std::string()));
		if (v6s.length()) {
			if (ipAddrs.length())
				ipAddrs.push_back(',');
			ipAddrs.append(v6s);
		}
	}

	std::vector<std::string> ipAddrsSplit(Utils::split(ipAddrs.c_str(),",","",""));
	for(std::vector<std::string>::const_iterator ipstr(ipAddrsSplit.begin());ipstr!=ipAddrsSplit.end();++ipstr) {
		InetAddress addr(*ipstr);
		switch(addr.ss_family) {
			case AF_INET:
				if ((!addr.netmaskBits())||(addr.netmaskBits() > 32))
					continue;
				break;
			case AF_INET6:
				if ((!addr.netmaskBits())||(addr.netmaskBits() > 128))
					continue;
				break;
			default: // ignore unrecognized address types or junk/empty fields
				continue;
		}
		_staticIps.push_back(addr);
	}
	if (_staticIps.size() > ZT1_MAX_ZT_ASSIGNED_ADDRESSES)
		throw std::invalid_argument("too many ZT-assigned IP addresses");
	std::sort(_staticIps.begin(),_staticIps.end());
	std::unique(_staticIps.begin(),_staticIps.end());

	std::vector<std::string> activeBridgesSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_ACTIVE_BRIDGES,"").c_str(),",","",""));
	for(std::vector<std::string>::const_iterator a(activeBridgesSplit.begin());a!=activeBridgesSplit.end();++a) {
		if (a->length() == ZT_ADDRESS_LENGTH_HEX) { // ignore empty or garbage fields
			Address tmp(*a);
			if (!tmp.isReserved())
				_activeBridges.push_back(tmp);
		}
	}
	std::sort(_activeBridges.begin(),_activeBridges.end());
	std::unique(_activeBridges.begin(),_activeBridges.end());

	Dictionary multicastRateEntries(d.get(ZT_NETWORKCONFIG_DICT_KEY_MULTICAST_RATES,std::string()));
	for(Dictionary::const_iterator i(multicastRateEntries.begin());i!=multicastRateEntries.end();++i) {
		std::vector<std::string> params(Utils::split(i->second.c_str(),",","",""));
		if (params.size() >= 3)
			_multicastRates[MulticastGroup(i->first)] = MulticastRate(Utils::hexStrToUInt(params[0].c_str()),Utils::hexStrToUInt(params[1].c_str()),Utils::hexStrToUInt(params[2].c_str()));
	}

	std::vector<std::string> relaysSplit(Utils::split(d.get(ZT_NETWORKCONFIG_DICT_KEY_RELAYS,"").c_str(),",","",""));
	for(std::vector<std::string>::const_iterator r(relaysSplit.begin());r!=relaysSplit.end();++r) {
		std::size_t semi(r->find(';')); // address;ip/port,...
		if (semi == ZT_ADDRESS_LENGTH_HEX) {
			std::pair<Address,InetAddress> relay(
				Address(r->substr(0,semi)),
				((r->length() > (semi + 1)) ? InetAddress(r->substr(semi + 1)) : InetAddress()) );
			if ((relay.first)&&(!relay.first.isReserved()))
				_relays.push_back(relay);
		}
	}
	std::sort(_relays.begin(),_relays.end());
	std::unique(_relays.begin(),_relays.end());

	_com.fromString(d.get(ZT_NETWORKCONFIG_DICT_KEY_CERTIFICATE_OF_MEMBERSHIP,std::string()));
}