|
|
|
|
@ -52,6 +52,10 @@
|
|
|
|
|
#include <utility> |
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
#include <ctype.h> |
|
|
|
|
#include <sys/utsname.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef IFNAMSIZ |
|
|
|
|
#define IFNAMSIZ 16 |
|
|
|
|
#endif |
|
|
|
|
@ -63,6 +67,35 @@ static const ZeroTier::MulticastGroup _blindWildcardMulticastGroup(ZeroTier::MAC
|
|
|
|
|
|
|
|
|
|
namespace ZeroTier { |
|
|
|
|
|
|
|
|
|
// determine if we're running a really old linux kernel.
|
|
|
|
|
// Kernels in the 2.6.x series don't behave the same when bringing up
|
|
|
|
|
// the tap devices.
|
|
|
|
|
//
|
|
|
|
|
// Returns true if the kernel major version is < 3
|
|
|
|
|
bool isOldLinuxKernel() { |
|
|
|
|
struct utsname buffer; |
|
|
|
|
char *p; |
|
|
|
|
long ver[16]; |
|
|
|
|
int i = 0; |
|
|
|
|
if (uname(&buffer) != 0) { |
|
|
|
|
perror("uname"); |
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
p = buffer.release; |
|
|
|
|
|
|
|
|
|
while (*p) { |
|
|
|
|
if (isdigit(*p)) { |
|
|
|
|
ver[i] = strtol(p, &p, 10); |
|
|
|
|
i++; |
|
|
|
|
} else { |
|
|
|
|
p++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return ver[0] < 3; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const char _base32_chars[32] = { 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','2','3','4','5','6','7' }; |
|
|
|
|
static void _base32_5_to_8(const uint8_t *in,char *out) |
|
|
|
|
{ |
|
|
|
|
@ -213,6 +246,13 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ifr.ifr_ifru.ifru_mtu = (int)_mtu; |
|
|
|
|
if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) { |
|
|
|
|
::close(sock); |
|
|
|
|
printf("WARNING: ioctl() failed setting up Linux tap device (set MTU)\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
usleep(100000); |
|
|
|
|
|
|
|
|
|
ifr.ifr_flags |= IFF_MULTICAST; |
|
|
|
|
@ -225,19 +265,21 @@ LinuxEthernetTap::LinuxEthernetTap(
|
|
|
|
|
|
|
|
|
|
usleep(100000); |
|
|
|
|
|
|
|
|
|
ifr.ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER; |
|
|
|
|
_mac.copyTo(ifr.ifr_ifru.ifru_hwaddr.sa_data,6); |
|
|
|
|
if (ioctl(sock,SIOCSIFHWADDR,(void *)&ifr) < 0) { |
|
|
|
|
::close(sock); |
|
|
|
|
printf("WARNING: ioctl() failed setting up Linux tap device (set MAC)\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (!isLinuxV2OrLess()) { |
|
|
|
|
ifr.ifr_ifru.ifru_hwaddr.sa_family = ARPHRD_ETHER; |
|
|
|
|
_mac.copyTo(ifr.ifr_ifru.ifru_hwaddr.sa_data,6); |
|
|
|
|
if (ioctl(sock,SIOCSIFHWADDR,(void *)&ifr) < 0) { |
|
|
|
|
::close(sock); |
|
|
|
|
printf("WARNING: ioctl() failed setting up Linux tap device (set MAC)\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ifr.ifr_ifru.ifru_mtu = (int)_mtu; |
|
|
|
|
if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) { |
|
|
|
|
::close(sock); |
|
|
|
|
printf("WARNING: ioctl() failed setting up Linux tap device (set MTU)\n"); |
|
|
|
|
return; |
|
|
|
|
ifr.ifr_ifru.ifru_mtu = (int)_mtu; |
|
|
|
|
if (ioctl(sock,SIOCSIFMTU,(void *)&ifr) < 0) { |
|
|
|
|
::close(sock); |
|
|
|
|
printf("WARNING: ioctl() failed setting up Linux tap device (set MTU)\n"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fcntl(_fd,F_SETFL,O_NONBLOCK); |
|
|
|
|
|