mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2024-12-18 20:47:53 +00:00
Version 0.4.3: fix Gentoo ip config failures and crashes
This version fixes problems with locating the 'ip' command on Gentoo and possibly other Linux systems, and a problem that could cause a crash if EthernetTap was unable to locate one of the commands it invokes to configure IP information on tap devices. The code also now builds on Windows. It doesn't run yet, but it's a step. Windows port is in full swing.
This commit is contained in:
parent
ce1a03bde3
commit
4ce88d7f72
@ -25,8 +25,10 @@
|
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include "Constants.hpp"
|
||||
#include "EthernetTap.hpp"
|
||||
#include "Logger.hpp"
|
||||
#include "RuntimeEnvironment.hpp"
|
||||
@ -59,31 +61,81 @@ static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC
|
||||
#include <net/if_arp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#ifdef __LINUX__
|
||||
// Command identifiers used with command finder static (on various *nixes)
|
||||
#define ZT_UNIX_IP_COMMAND 1
|
||||
#define ZT_UNIX_IFCONFIG_COMMAND 2
|
||||
#define ZT_MAC_KEXTLOAD_COMMAND 3
|
||||
#define ZT_MAC_IPCONFIG_COMMAND 4
|
||||
|
||||
// Finds external commands on startup
|
||||
class _CommandFinder
|
||||
{
|
||||
public:
|
||||
_CommandFinder()
|
||||
{
|
||||
_findCmd(ZT_UNIX_IFCONFIG_COMMAND,"ifconfig");
|
||||
#ifdef __LINUX__
|
||||
_findCmd(ZT_UNIX_IP_COMMAND,"ip");
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
_findCmd(ZT_MAC_KEXTLOAD_COMMAND,"kextload");
|
||||
_findCmd(ZT_MAC_IPCONFIG_COMMAND,"ipconfig");
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns NULL if command was not found
|
||||
inline const char *operator[](int id) const
|
||||
throw()
|
||||
{
|
||||
std::map<int,std::string>::const_iterator c(_paths.find(id));
|
||||
if (c == _paths.end())
|
||||
return (const char *)0;
|
||||
return c->second.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
inline void _findCmd(int id,const char *name)
|
||||
{
|
||||
char tmp[4096];
|
||||
sprintf(tmp,"/sbin/%s",name);
|
||||
if (ZeroTier::Utils::fileExists(tmp)) {
|
||||
_paths[id] = tmp;
|
||||
return;
|
||||
}
|
||||
sprintf(tmp,"/usr/sbin/%s",name);
|
||||
if (ZeroTier::Utils::fileExists(tmp)) {
|
||||
_paths[id] = tmp;
|
||||
return;
|
||||
}
|
||||
sprintf(tmp,"/bin/%s",name);
|
||||
if (ZeroTier::Utils::fileExists(tmp)) {
|
||||
_paths[id] = tmp;
|
||||
return;
|
||||
}
|
||||
sprintf(tmp,"/usr/bin/%s",name);
|
||||
if (ZeroTier::Utils::fileExists(tmp)) {
|
||||
_paths[id] = tmp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::map<int,std::string> _paths;
|
||||
};
|
||||
static const _CommandFinder UNIX_COMMANDS;
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_tun.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#define ZT_ETHERTAP_IP_COMMAND "/sbin/ip"
|
||||
#define ZT_ETHERTAP_SYSCTL_COMMAND "/sbin/sysctl"
|
||||
|
||||
#endif // __LINUX__
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
#include <sys/uio.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#define ZT_ETHERTAP_IFCONFIG "/sbin/ifconfig"
|
||||
#define ZT_MAC_KEXTLOAD "/sbin/kextload"
|
||||
#define ZT_MAC_IPCONFIG "/usr/sbin/ipconfig"
|
||||
|
||||
#endif // __APPLE__
|
||||
|
||||
namespace ZeroTier {
|
||||
@ -214,14 +266,15 @@ EthernetTap::EthernetTap(
|
||||
throw std::runtime_error("max tap MTU is 4096");
|
||||
|
||||
// Check for existence of ZT tap devices, try to load module if not there
|
||||
if (stat("/dev/zt0",&tmp)) {
|
||||
int kextpid;
|
||||
const char *kextload = UNIX_COMMANDS[ZT_MAC_KEXTLOAD_COMMAND];
|
||||
if ((stat("/dev/zt0",&tmp))&&(kextload)) {
|
||||
long kextpid;
|
||||
char tmp[4096];
|
||||
strcpy(tmp,_r->homePath.c_str());
|
||||
if ((kextpid = (int)vfork()) == 0) {
|
||||
if ((kextpid = (long)vfork()) == 0) {
|
||||
chdir(tmp);
|
||||
execl(ZT_MAC_KEXTLOAD,ZT_MAC_KEXTLOAD,"-q","-repository",tmp,"tap.kext",(const char *)0);
|
||||
exit(-1);
|
||||
execl(kextload,kextload,"-q","-repository",tmp,"tap.kext",(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(kextpid,&exitcode,0);
|
||||
@ -250,14 +303,19 @@ EthernetTap::EthernetTap(
|
||||
throw std::runtime_error("unable to set flags on file descriptor for TAP device");
|
||||
}
|
||||
|
||||
sprintf(ethaddr,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
|
||||
sprintf(mtustr,"%u",mtu);
|
||||
const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND];
|
||||
if (!ifconfig) {
|
||||
::close(_fd);
|
||||
throw std::runtime_error("unable to find 'ifconfig' command on system");
|
||||
}
|
||||
|
||||
// Configure MAC address and MTU, bring interface up
|
||||
sprintf(ethaddr,"%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",(int)mac[0],(int)mac[1],(int)mac[2],(int)mac[3],(int)mac[4],(int)mac[5]);
|
||||
sprintf(mtustr,"%u",mtu);
|
||||
long cpid;
|
||||
if ((cpid = (long)vfork()) == 0) {
|
||||
execl(ZT_ETHERTAP_IFCONFIG,ZT_ETHERTAP_IFCONFIG,_dev,"lladdr",ethaddr,"mtu",mtustr,"up",(const char *)0);
|
||||
exit(-1);
|
||||
execl(ifconfig,ifconfig,_dev,"lladdr",ethaddr,"mtu",mtustr,"up",(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
@ -285,15 +343,15 @@ EthernetTap::~EthernetTap()
|
||||
#ifdef __APPLE__
|
||||
void EthernetTap::whack()
|
||||
{
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
execl(ZT_MAC_IPCONFIG,ZT_MAC_IPCONFIG,"set",_dev,"AUTOMATIC-V6",(const char *)0);
|
||||
exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
if (exitcode) {
|
||||
LOG("%s: ipconfig set AUTOMATIC-V6 failed",_dev);
|
||||
const char *ipconfig = UNIX_COMMANDS[ZT_MAC_IPCONFIG_COMMAND];
|
||||
if (ipconfig) {
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
execl(ipconfig,ipconfig,"set",_dev,"AUTOMATIC-V6",(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -304,12 +362,15 @@ void EthernetTap::whack() {}
|
||||
#ifdef __LINUX__
|
||||
static bool ___removeIp(const char *_dev,const InetAddress &ip)
|
||||
{
|
||||
const char *ipcmd = UNIX_COMMANDS[ZT_UNIX_IP_COMMAND];
|
||||
if (!ipcmd)
|
||||
return false;
|
||||
long cpid = (long)vfork();
|
||||
if (cpid == 0) {
|
||||
execl(ZT_ETHERTAP_IP_COMMAND,ZT_ETHERTAP_IP_COMMAND,"addr","del",ip.toString().c_str(),"dev",_dev,(const char *)0);
|
||||
exit(1); /* not reached unless exec fails */
|
||||
execl(ipcmd,ipcmd,"addr","del",ip.toString().c_str(),"dev",_dev,(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = 1;
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
return (exitcode == 0);
|
||||
}
|
||||
@ -317,6 +378,12 @@ static bool ___removeIp(const char *_dev,const InetAddress &ip)
|
||||
|
||||
bool EthernetTap::addIP(const InetAddress &ip)
|
||||
{
|
||||
const char *ipcmd = UNIX_COMMANDS[ZT_UNIX_IP_COMMAND];
|
||||
if (!ipcmd) {
|
||||
LOG("ERROR: could not configure IP address for %s: unable to find 'ip' command on system (checked /sbin, /bin, /usr/sbin, /usr/bin)",_dev);
|
||||
return false;
|
||||
}
|
||||
|
||||
Mutex::Lock _l(_ips_m);
|
||||
|
||||
if (!ip)
|
||||
@ -338,8 +405,8 @@ bool EthernetTap::addIP(const InetAddress &ip)
|
||||
|
||||
long cpid;
|
||||
if ((cpid = (long)vfork()) == 0) {
|
||||
execl(ZT_ETHERTAP_IP_COMMAND,ZT_ETHERTAP_IP_COMMAND,"addr","add",ip.toString().c_str(),"dev",_dev,(const char *)0);
|
||||
exit(-1);
|
||||
execl(ipcmd,ipcmd,"addr","add",ip.toString().c_str(),"dev",_dev,(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
@ -356,10 +423,13 @@ bool EthernetTap::addIP(const InetAddress &ip)
|
||||
#ifdef __APPLE__
|
||||
static bool ___removeIp(const char *_dev,const InetAddress &ip)
|
||||
{
|
||||
int cpid;
|
||||
if ((cpid = (int)vfork()) == 0) {
|
||||
execl(ZT_ETHERTAP_IFCONFIG,ZT_ETHERTAP_IFCONFIG,_dev,"inet",ip.toIpString().c_str(),"-alias",(const char *)0);
|
||||
exit(-1);
|
||||
const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND];
|
||||
if (!ifconfig)
|
||||
return false;
|
||||
long cpid;
|
||||
if ((cpid = (long)vfork()) == 0) {
|
||||
execl(ifconfig,ifconfig,_dev,"inet",ip.toIpString().c_str(),"-alias",(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
@ -370,6 +440,12 @@ static bool ___removeIp(const char *_dev,const InetAddress &ip)
|
||||
|
||||
bool EthernetTap::addIP(const InetAddress &ip)
|
||||
{
|
||||
const char *ifconfig = UNIX_COMMANDS[ZT_UNIX_IFCONFIG_COMMAND];
|
||||
if (!ifconfig) {
|
||||
LOG("ERROR: could not configure IP address for %s: unable to find 'ifconfig' command on system (checked /sbin, /bin, /usr/sbin, /usr/bin)",_dev);
|
||||
return false;
|
||||
}
|
||||
|
||||
Mutex::Lock _l(_ips_m);
|
||||
|
||||
if (!ip)
|
||||
@ -389,10 +465,10 @@ bool EthernetTap::addIP(const InetAddress &ip)
|
||||
}
|
||||
}
|
||||
|
||||
int cpid;
|
||||
if ((cpid = (int)vfork()) == 0) {
|
||||
execl(ZT_ETHERTAP_IFCONFIG,ZT_ETHERTAP_IFCONFIG,_dev,ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0);
|
||||
exit(-1);
|
||||
long cpid;
|
||||
if ((cpid = (long)vfork()) == 0) {
|
||||
execl(ifconfig,ifconfig,_dev,ip.isV4() ? "inet" : "inet6",ip.toString().c_str(),"alias",(const char *)0);
|
||||
_exit(-1);
|
||||
} else {
|
||||
int exitcode = -1;
|
||||
waitpid(cpid,&exitcode,0);
|
||||
|
Loading…
Reference in New Issue
Block a user