Browse Source

Unload the mac kext on exit.

Adam Ierymenko 11 years ago
parent
commit
a6dc4caecf
1 changed files with 32 additions and 0 deletions
  1. 32 0
      node/EthernetTap.cpp

+ 32 - 0
node/EthernetTap.cpp

@@ -69,6 +69,7 @@ static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC
 #define ZT_UNIX_IFCONFIG_COMMAND 2
 #define ZT_MAC_KEXTLOAD_COMMAND 3
 #define ZT_MAC_IPCONFIG_COMMAND 4
+#define ZT_MAC_KEXTUNLOAD_COMMAND 5
 
 // Finds external commands on startup
 class _CommandFinder
@@ -83,6 +84,7 @@ public:
 #ifdef __APPLE__
 		_findCmd(ZT_MAC_KEXTLOAD_COMMAND,"kextload");
 		_findCmd(ZT_MAC_IPCONFIG_COMMAND,"ipconfig");
+		_findCmd(ZT_MAC_KEXTUNLOAD_COMMAND,"kextunload");
 #endif
 	}
 
@@ -139,6 +141,9 @@ static const _CommandFinder UNIX_COMMANDS;
 #include <net/route.h>
 #include <net/if_dl.h>
 #include <ifaddrs.h>
+
+static volatile int EthernetTap_instances = 0;
+static ZeroTier::Mutex EthernetTap_instances_m;
 #endif // __APPLE__
 
 namespace ZeroTier {
@@ -337,6 +342,10 @@ EthernetTap::EthernetTap(
 	::pipe(_shutdownSignalPipe);
 
 	_thread = Thread::start(this);
+
+	EthernetTap_instances_m.lock();
+	++EthernetTap_instances;
+	EthernetTap_instances_m.unlock();
 }
 #endif // __APPLE__
 
@@ -345,6 +354,29 @@ EthernetTap::~EthernetTap()
 	::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit
 	Thread::join(_thread);
 	::close(_fd);
+
+#ifdef __APPLE__
+	EthernetTap_instances_m.lock();
+	int instances = --EthernetTap_instances;
+	EthernetTap_instances_m.unlock();
+	if (instances <= 0) {
+		// Unload OSX kernel extension on the deletion of the last EthernetTap
+		// instance.
+		const char *kextunload = UNIX_COMMANDS[ZT_MAC_KEXTUNLOAD_COMMAND];
+		if (kextunload) {
+			long kextpid;
+			char tmp[4096];
+			sprintf(tmp,"%s/tap.kext",_r->homePath.c_str());
+			if ((kextpid = (long)vfork()) == 0) {
+				execl(kextunload,kextunload,tmp,(const char *)0);
+				_exit(-1);
+			} else if (kextpid > 0) {
+				int exitcode = -1;
+				waitpid(kextpid,&exitcode,0);
+			}
+		}
+	}
+#endif // __APPLE__
 }
 
 #ifdef __APPLE__