From fdf4ebd43c93ef3c0f864ca1ab5bb40c7283c2fc Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 7 Feb 2022 17:10:54 -0800 Subject: [PATCH 1/2] potential fix for 2.6.x kernels detect if the kernel is super old. if so, do not execute the post IF_UP commands on the interface --- osdep/LinuxEthernetTap.cpp | 66 +++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 35a123873..0225fdd59 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -52,6 +52,10 @@ #include #include +#include +#include + + #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); From 5d63ed67397d8c247395da7931a5c70ed3126a07 Mon Sep 17 00:00:00 2001 From: Grant Limberg Date: Mon, 7 Feb 2022 17:14:43 -0800 Subject: [PATCH 2/2] fix function call --- osdep/LinuxEthernetTap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osdep/LinuxEthernetTap.cpp b/osdep/LinuxEthernetTap.cpp index 0225fdd59..9a178e26b 100644 --- a/osdep/LinuxEthernetTap.cpp +++ b/osdep/LinuxEthernetTap.cpp @@ -265,7 +265,7 @@ LinuxEthernetTap::LinuxEthernetTap( usleep(100000); - if (!isLinuxV2OrLess()) { + if (!isOldLinuxKernel()) { 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) {