From 3ff5c061d7a540727abccb1805198ca1a6dd9c75 Mon Sep 17 00:00:00 2001 From: Davide Beatrici Date: Thu, 23 Aug 2018 10:56:30 +0200 Subject: [PATCH] Add TAP devices support for FreeBSD and OpenBSD Thanks to @kennylam777 for the first implementation: https://github.com/kennylam777/SoftEtherVPN/commits/FreeBSD-TAP --- src/CMakeLists.txt | 6 +++--- src/Cedar/BridgeUnix.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/Cedar/Cedar.h | 10 +++++----- src/Cedar/Server.c | 5 +++-- src/Cedar/VLanUnix.c | 40 ++++++++++++++++++++++------------------ 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4f37bd18..afd0fe10 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,13 +50,13 @@ if(UNIX) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") - add_definitions(-DUNIX_BSD -DBRIDGE_BPF -DNO_VLAN) + add_definitions(-DUNIX_BSD -DBRIDGE_BPF) include_directories(SYSTEM /usr/local/include) link_directories(SYSTEM /usr/local/lib) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") - add_definitions(-DUNIX_BSD -DNO_VLAN) + add_definitions(-DUNIX_BSD -DUNIX_OPENBSD) include_directories(SYSTEM /usr/local/include) link_directories(SYSTEM /usr/local/lib) endif() @@ -66,7 +66,7 @@ if(UNIX) endif() if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") - add_definitions(-DUNIX_MACOS -DBRIDGE_PCAP) + add_definitions(-DUNIX_BSD -DUNIX_MACOS -DBRIDGE_PCAP) endif() endif() diff --git a/src/Cedar/BridgeUnix.c b/src/Cedar/BridgeUnix.c index 50a0c0bd..d459b286 100644 --- a/src/Cedar/BridgeUnix.c +++ b/src/Cedar/BridgeUnix.c @@ -1491,12 +1491,52 @@ ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr) } #endif // BRIDGE_BPF +#ifdef UNIX_BSD +ETH *OpenEthBSD(name, local, tapmode, tapaddr) +{ + if (tapmode) + { +#ifndef NO_VLAN + // In tap mode + VLAN *v = NewTap(name, tapaddr, true); + if (v == NULL) + { + return NULL; + } + + ETH *e; + e = ZeroMalloc(sizeof(ETH)); + e->Name = CopyStr(name); + e->Title = CopyStr(name); + e->Cancel = VLanGetCancel(v); + e->IfIndex = 0; + e->Socket = INVALID_SOCKET; + e->Tap = v; + + return e; +#else // NO_VLAN + return NULL: +#endif // NO_VLAN + } + +#if defined(BRIDGE_BPF) + return OpenEthBpf(name, local, tapmode, tapaddr); +#elif defined(BRIDGE_PCAP) + return OpenEthPcap(name, local, tapmode, tapaddr); +#else + return NULL; +#endif +} +#endif // UNIX_BSD + // Open Ethernet adapter ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr) { #if defined(UNIX_LINUX) return OpenEthLinux(name, local, tapmode, tapaddr); +#elif defined(UNIX_BSD) + return OpenEthBSD(name, local, tapmode, tapaddr); #elif defined(UNIX_SOLARIS) return OpenEthSolaris(name, local, tapmode, tapaddr); #elif defined(BRIDGE_PCAP) diff --git a/src/Cedar/Cedar.h b/src/Cedar/Cedar.h index 7db8ce31..c0118545 100644 --- a/src/Cedar/Cedar.h +++ b/src/Cedar/Cedar.h @@ -746,14 +746,14 @@ #define TAP_FILENAME_1 "/dev/net/tun" #define TAP_FILENAME_2 "/dev/tun" -#ifdef UNIX_MACOS +#ifdef UNIX_BSD #ifdef NO_VLAN -#define TAP_MACOS_FILENAME "/dev/tap0" +#define TAP_BSD_FILENAME "/dev/tap0" #else // NO_VLAN -#define TAP_MACOS_FILENAME "tap" +#define TAP_BSD_FILENAME "tap" #endif // NO_VLAN -#define TAP_MACOS_DIR "/dev/" -#define TAP_MACOS_NUMBER (16) +#define TAP_BSD_DIR "/dev/" +#define TAP_BSD_NUMBER (16) #endif // UNIX_MACOS diff --git a/src/Cedar/Server.c b/src/Cedar/Server.c index b309dfa2..fc5ba0ce 100644 --- a/src/Cedar/Server.c +++ b/src/Cedar/Server.c @@ -1616,8 +1616,9 @@ void GetServerCapsMain(SERVER *s, CAPSLIST *t) if (IsBridgeSupported()) { - // Tun / tap device is available (only Linux) - AddCapsBool(t, "b_tap_supported", GetOsInfo()->OsType == OSTYPE_LINUX ? true : false); + // TUN / TAP device availability (Linux and BSD) + const UINT OsType = GetOsInfo()->OsType; + AddCapsBool(t, "b_tap_supported", OsType == OSTYPE_LINUX || OsType == OSTYPE_BSD); } // Cascade connection diff --git a/src/Cedar/VLanUnix.c b/src/Cedar/VLanUnix.c index c7e1c99e..54fb2d0c 100644 --- a/src/Cedar/VLanUnix.c +++ b/src/Cedar/VLanUnix.c @@ -126,9 +126,13 @@ #include #include #include -#ifdef UNIX_MACOS +#ifdef UNIX_BSD +#ifdef UNIX_OPENBSD +#include +#else // UNIX_OPENBSD #include -#endif +#endif // UNIX_OPENBSD +#endif // UNIX_BSD #ifdef OS_UNIX @@ -445,8 +449,8 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre struct sockaddr sa; char *tap_name = TAP_FILENAME_1; int s; -#ifdef UNIX_MACOS - char tap_macos_name[256] = TAP_MACOS_DIR TAP_MACOS_FILENAME; +#ifdef UNIX_BSD + char tap_bsd_name[256] = TAP_BSD_DIR TAP_BSD_FILENAME; #endif // Validate arguments if (name == NULL) @@ -457,7 +461,7 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre GenerateTunName(name, prefix, eth_name, sizeof(eth_name)); // Open the tun / tap -#ifndef UNIX_MACOS +#ifndef UNIX_BSD if (GetOsInfo()->OsType == OSTYPE_LINUX) { // Linux @@ -472,7 +476,7 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre Run("chmod", tmp, true, true); } } - // Other than MacOS X + fd = open(TAP_FILENAME_1, O_RDWR); if (fd == -1) { @@ -484,16 +488,16 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre } tap_name = TAP_FILENAME_2; } -#else // UNIX_MACOS +#else // UNIX_BSD { int i; fd = -1; - for (i = 0; i < TAP_MACOS_NUMBER; i++) { - sprintf(tap_macos_name + strlen(TAP_MACOS_DIR TAP_MACOS_FILENAME), "%d", i); - fd = open(tap_macos_name, O_RDWR); + for (i = 0; i < TAP_BSD_NUMBER; i++) { + sprintf(tap_bsd_name + strlen(TAP_BSD_DIR TAP_BSD_FILENAME), "%d", i); + fd = open(tap_bsd_name, O_RDWR); if (fd != -1) { - tap_name = tap_macos_name; + tap_name = tap_bsd_name; break; } } @@ -502,7 +506,7 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre return -1; } } -#endif // UNIX_MACOS +#endif // UNIX_BSD #ifdef UNIX_LINUX // Create a tap for Linux @@ -547,18 +551,18 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre } #else // UNIX_LINUX -#ifdef UNIX_MACOS +#ifdef UNIX_BSD // MAC address setting s = socket(AF_INET, SOCK_DGRAM, 0); if (s != -1) { - char *macos_eth_name; - macos_eth_name = tap_macos_name + strlen(TAP_MACOS_DIR); + char *bsd_eth_name; + bsd_eth_name = tap_bsd_name + strlen(TAP_BSD_DIR); if (mac_address != NULL) { Zero(&ifr, sizeof(ifr)); - StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), macos_eth_name); + StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), bsd_eth_name); ifr.ifr_addr.sa_len = ETHER_ADDR_LEN; ifr.ifr_addr.sa_family = AF_LINK; Copy(&ifr.ifr_addr.sa_data, mac_address, ETHER_ADDR_LEN); @@ -566,7 +570,7 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre } Zero(&ifr, sizeof(ifr)); - StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), macos_eth_name); + StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), bsd_eth_name); ioctl(s, SIOCGIFFLAGS, &ifr); if (create_up) @@ -577,7 +581,7 @@ int UnixCreateTapDeviceEx(char *name, char *prefix, UCHAR *mac_address, bool cre close(s); } -#endif // UNIX_MACOS +#endif // UNIX_BSD #ifdef UNIX_SOLARIS // Create a tap for Solaris {