diff options
-rw-r--r-- | node/EthernetTap.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/node/EthernetTap.cpp b/node/EthernetTap.cpp index 44118c2a..d8de55d2 100644 --- a/node/EthernetTap.cpp +++ b/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__ |