diff --git a/osdep/MacEthernetTap.cpp b/osdep/MacEthernetTap.cpp index 1e538e883..a1d68c5ae 100644 --- a/osdep/MacEthernetTap.cpp +++ b/osdep/MacEthernetTap.cpp @@ -79,6 +79,7 @@ MacEthernetTap::MacEthernetTap( _homePath(homePath), _mtu(mtu), _metric(metric), + _devNo(0), _agentStdin(-1), _agentStdout(-1), _agentStderr(-1), @@ -97,7 +98,7 @@ MacEthernetTap::MacEthernetTap( agentPath.push_back(ZT_PATH_SEPARATOR); agentPath.append("MacEthernetTapAgent"); if (!OSUtils::fileExists(agentPath.c_str())) - throw std::runtime_error("MacEthernetTapAgent not installed in ZeroTier home"); + throw std::runtime_error("MacEthernetTapAgent not present in ZeroTier home"); Mutex::Lock _gl(globalTapCreateLock); // only make one at a time @@ -112,7 +113,7 @@ MacEthernetTap::MacEthernetTap( while (p) { int nameLen = (int)strlen(p->ifa_name); // Delete feth# from feth0 to feth9999, but don't touch >10000. - if ((!strncmp(p->ifa_name,"feth",4))&&(nameLen >= 5)&&(nameLen < 9)&&(deleted.count(std::string(p->ifa_name)) == 0)) { + if ((!strncmp(p->ifa_name,"feth",4))&&(nameLen >= 5)&&(nameLen <= 8)&&(deleted.count(std::string(p->ifa_name)) == 0)) { deleted.insert(std::string(p->ifa_name)); const char *args[4]; args[0] = "/sbin/ifconfig"; @@ -156,10 +157,11 @@ MacEthernetTap::MacEthernetTap( if (devNo < 100) devNo = 100; } else { + _dev = devstr; + _devNo = devNo; break; } } - _dev = devstr; if (::pipe(_shutdownSignalPipe)) throw std::runtime_error("pipe creation failed"); @@ -204,22 +206,60 @@ MacEthernetTap::MacEthernetTap( MacEthernetTap::~MacEthernetTap() { + char tmp[64]; + const char *args[4]; + pid_t pid0,pid1; + MacDNSHelper::removeDNS(_nwid); - + Mutex::Lock _gl(globalTapCreateLock); ::write(_shutdownSignalPipe[1],"\0",1); // causes thread to exit - Thread::join(_thread); ::close(_shutdownSignalPipe[0]); ::close(_shutdownSignalPipe[1]); + int ec = 0; - ::kill(_agentPid,SIGTERM); - ::waitpid(_agentPid,&ec,0); + ::kill(_agentPid,SIGKILL); + ::close(_agentStdin); ::close(_agentStdout); ::close(_agentStderr); ::close(_agentStdin2); ::close(_agentStdout2); ::close(_agentStderr2); + + ::waitpid(_agentPid,&ec,0); + + args[0] = "/sbin/ifconfig"; + args[1] = _dev.c_str(); + args[2] = "destroy"; + args[3] = (char *)0; + pid0 = vfork(); + if (pid0 == 0) { + execv(args[0],const_cast(args)); + _exit(-1); + } + + snprintf(tmp,sizeof(tmp),"feth%u",_devNo + 5000); + //args[0] = "/sbin/ifconfig"; + args[1] = tmp; + //args[2] = "destroy"; + //args[3] = (char *)0; + pid1 = vfork(); + if (pid1 == 0) { + execv(args[0],const_cast(args)); + _exit(-1); + } + + if (pid0 > 0) { + int rv = 0; + waitpid(pid0,&rv,0); + } + if (pid1 > 0) { + int rv = 0; + waitpid(pid1,&rv,0); + } + + Thread::join(_thread); } void MacEthernetTap::setEnabled(bool en) { _enabled = en; } diff --git a/osdep/MacEthernetTap.hpp b/osdep/MacEthernetTap.hpp index c9f9a3b22..4b02999b9 100644 --- a/osdep/MacEthernetTap.hpp +++ b/osdep/MacEthernetTap.hpp @@ -72,6 +72,7 @@ private: Mutex _putLock; unsigned int _mtu; unsigned int _metric; + unsigned int _devNo; int _shutdownSignalPipe[2]; int _agentStdin,_agentStdout,_agentStderr,_agentStdin2,_agentStdout2,_agentStderr2; long _agentPid; diff --git a/osdep/MacEthernetTapAgent.c b/osdep/MacEthernetTapAgent.c index 361018e28..3a44eadd2 100644 --- a/osdep/MacEthernetTapAgent.c +++ b/osdep/MacEthernetTapAgent.c @@ -29,13 +29,13 @@ * is limited to 2048. AF_NDRV packet injection is required to inject * ZeroTier's large MTU frames. * - * Benchmarks show that this performs similarly to the old tap.kext driver, - * and a kext is no longer required. Splitting it off into an agent will - * also make it easier to have zerotier-one itself drop permissions. - * * All this stuff is basically undocumented. A lot of tracing through * the Darwin/XNU kernel source was required to figure out how to make * this actually work. + * + * We hope to develop a DriverKit-based driver in the near-mid future to + * replace this weird hack, but it works for now through Big Sur in our + * testing. * * See also: *