Browse Source

IP assignment and change cleanup -- leave IPs that were never configured via ZT static assignment alone.

Adam Ierymenko 11 years ago
parent
commit
d02ecfb288
2 changed files with 41 additions and 47 deletions
  1. 0 44
      node/EthernetTap.hpp
  2. 41 3
      node/Network.cpp

+ 0 - 44
node/EthernetTap.hpp

@@ -115,50 +115,6 @@ public:
 	 */
 	virtual std::set<InetAddress> ips() const = 0;
 
-	/**
-	 * Set this tap's IP addresses to exactly this set of IPs
-	 *
-	 * New IPs are created. Any IP that overlaps with the network of an IP in
-	 * this list is removed, but other IPs are left intact.
-	 *
-	 * @param ips IP addresses with netmask in port field
-	 */
-	inline void setIps(const std::set<InetAddress> &allIps)
-	{
-		for(std::set<InetAddress>::iterator i(allIps.begin());i!=allIps.end();++i)
-			addIP(*i);
-		std::set<InetAddress> myIps(ips());
-#ifdef __APPLE__
-		bool haveV6LinkLocal = false;
-		for(std::set<InetAddress>::iterator i(myIps.begin());i!=myIps.end();++i) {
-			if (i->isLinkLocal()) {
-				if (i->isV6())
-					haveV6LinkLocal = true;
-			} else if (!allIps.count(*i)) {
-				for(std::set<InetAddress>::const_iterator i2(allIps.begin());i2!=allIps.end();++i2) {
-					if (i->sameNetworkAs(*i2)) {
-						removeIP(*i);
-						break;
-					}
-				}
-			}
-		}
-		if (!haveV6LinkLocal)
-			addIP(InetAddress::makeIpv6LinkLocal(_mac));
-#else
-		for(std::set<InetAddress>::iterator i(myIps.begin());i!=myIps.end();++i) {
-			if ((!i->isLinkLocal())&&(!allIps.count(*i))) {
-				for(std::set<InetAddress>::const_iterator i2(allIps.begin());i2!=allIps.end();++i2) {
-					if (i->sameNetworkAs(*i2)) {
-						removeIP(*i);
-						break;
-					}
-				}
-			}
-		}
-#endif
-	}
-
 	/**
 	 * Put a frame, making it available to the OS for processing
 	 *

+ 41 - 3
node/Network.cpp

@@ -150,6 +150,10 @@ bool Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
 	try {
 		SharedPtr<NetworkConfig> newConfig(new NetworkConfig(conf)); // throws if invalid
 		if ((newConfig->networkId() == _id)&&(newConfig->issuedTo() == _r->identity.address())) {
+			std::set<InetAddress> oldStaticIps;
+			if (_config)
+				oldStaticIps = _config->staticIps();
+
 			_config = newConfig;
 
 			_lastConfigUpdate = Utils::now();
@@ -168,8 +172,40 @@ bool Network::setConfiguration(const Dictionary &conf,bool saveToDisk)
 			if (t) {
 				char fname[1024];
 				_mkNetworkFriendlyName(fname,sizeof(fname));
-				t->setIps(newConfig->staticIps());
 				t->setFriendlyName(fname);
+
+				// Remove previously configured static IPs that are gone
+				for(std::set<InetAddress>::const_iterator oldip(oldStaticIps.begin());oldip!=oldStaticIps.end();++oldip) {
+					if (!_config->staticIps().count(*oldip))
+						t->removeIP(*oldip);
+				}
+
+				// Add new static IPs that were not in previous config
+				for(std::set<InetAddress>::const_iterator newip(_config->staticIps().begin());newip!=_config->staticIps().end();++newip) {
+					if (!oldStaticIps.count(*newip))
+						t->addIP(*newip);
+				}
+
+#ifdef __APPLE__
+				// Make sure there's an IPv6 link-local address on Macs if IPv6 is enabled
+				// Other OSes don't need this -- Mac seems not to want to auto-assign
+				// This might go away once we integrate properly w/Mac network setup stuff.
+				if (_config->permitsEtherType(ZT_ETHERTYPE_IPV6)) {
+					bool haveV6LinkLocal = false;
+					std::set<InetAddress> ips(t->ips());
+					for(std::set<InetAddress>::const_iterator i(ips.begin());i!=ips.end();++i) {
+						if ((i->isV6())&&(i->isLinkLocal())) {
+							haveV6LinkLocal = true;
+							break;
+						}
+					}
+					if (!haveV6LinkLocal)
+						t->addIP(InetAddress::makeIpv6LinkLocal(_mac));
+				}
+#endif // __APPLE__
+
+				// ... IPs that were never controlled by static assignment are left
+				// alone, as these may be DHCP or user-configured.
 			} else {
 				if (!_setupThread)
 					_setupThread = Thread::start<Network>(this);
@@ -371,8 +407,10 @@ void Network::threadMain()
 			_r->tapFactory->close(_tap,false);
 		_tap = t;
 		if (t) {
-			if (_config)
-				t->setIps(_config->staticIps());
+			if (_config) {
+				for(std::set<InetAddress>::const_iterator newip(_config->staticIps().begin());newip!=_config->staticIps().end();++newip)
+					t->addIP(*newip);
+			}
 			t->setEnabled(_enabled);
 		}
 	}