summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2014-08-02 04:17:57 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2014-08-02 06:08:18 +0200
commit96a291d11f884b18356ba8ef4b12b82d658d8d04 (patch)
tree8ad328375c4b1754e69cd38ee4e2e13d60c28525
parente63fe3b8d058bed15d65728f8e9a7e4093040028 (diff)
downloadfastd-96a291d11f884b18356ba8ef4b12b82d658d8d04.tar
fastd-96a291d11f884b18356ba8ef4b12b82d658d8d04.zip
Add support for Mac OS X
-rw-r--r--cmake/checks.cmake20
-rw-r--r--cmake/config.cmake9
-rw-r--r--cmake/deps.cmake12
-rw-r--r--src/CMakeLists.txt6
-rw-r--r--src/compat.h36
-rw-r--r--src/config.c10
-rw-r--r--src/fastd_config.h.in3
-rw-r--r--src/poll.c62
-rw-r--r--src/tuntap.c57
9 files changed, 189 insertions, 26 deletions
diff --git a/cmake/checks.cmake b/cmake/checks.cmake
index 62d10d0..64dae58 100644
--- a/cmake/checks.cmake
+++ b/cmake/checks.cmake
@@ -38,18 +38,20 @@ int main() {
check_prototype_definition("get_current_dir_name" "char *get_current_dir_name(void)" "NULL" "unistd.h" HAVE_GET_CURRENT_DIR_NAME)
-set(RT_LIBRARY "")
-check_symbol_exists("clock_gettime" "time.h" HAVE_CLOCK_GETTIME)
+if(NOT DARWIN)
+ set(RT_LIBRARY "")
+ check_symbol_exists("clock_gettime" "time.h" HAVE_CLOCK_GETTIME)
-if(NOT HAVE_CLOCK_GETTIME)
- set(RT_LIBRARY "rt")
- list(APPEND CMAKE_REQUIRED_LIBRARIES "rt")
+ if(NOT HAVE_CLOCK_GETTIME)
+ set(RT_LIBRARY "rt")
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "rt")
- check_symbol_exists("clock_gettime" "time.h" HAVE_CLOCK_GETTIME_RT)
- if(NOT HAVE_CLOCK_GETTIME_RT)
+ check_symbol_exists("clock_gettime" "time.h" HAVE_CLOCK_GETTIME_RT)
+ if(NOT HAVE_CLOCK_GETTIME_RT)
message(FATAL_ERROR "clock_gettime() not found")
- endif(NOT HAVE_CLOCK_GETTIME_RT)
-endif(NOT HAVE_CLOCK_GETTIME)
+ endif(NOT HAVE_CLOCK_GETTIME_RT)
+ endif(NOT HAVE_CLOCK_GETTIME)
+endif(NOT DARWIN)
set(CMAKE_EXTRA_INCLUDE_FILES "netinet/if_ether.h")
diff --git a/cmake/config.cmake b/cmake/config.cmake
index e77abc8..c40ee9f 100644
--- a/cmake/config.cmake
+++ b/cmake/config.cmake
@@ -4,6 +4,12 @@ else()
set(LINUX FALSE)
endif()
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(DARWIN TRUE)
+else()
+ set(DARWIN FALSE)
+endif()
+
set(USE_BINDTODEVICE ${LINUX})
set(USE_EPOLL ${LINUX})
@@ -12,6 +18,9 @@ set(USE_PMTU ${LINUX})
set(USE_PKTINFO ${LINUX})
set(USE_PACKET_MARK ${LINUX})
+# OSX doesn't support poll on devices...
+set(USE_SELECT ${DARWIN})
+
if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
set(USE_MULTIAF_BIND FALSE)
else()
diff --git a/cmake/deps.cmake b/cmake/deps.cmake
index d9dff1e..ea5a0a0 100644
--- a/cmake/deps.cmake
+++ b/cmake/deps.cmake
@@ -1,11 +1,11 @@
-find_package(BISON 2.5 REQUIRED)
+set(PTHREAD_CFLAGS -pthread)
+
+if(NOT DARWIN)
+ set(PTHREAD_LDFLAGS -pthread)
+endif(NOT DARWIN)
-set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
-find_package(Threads)
-if(NOT CMAKE_USE_PTHREADS_INIT)
- MESSAGE(FATAL_ERROR "No pthread support found.")
-endif(NOT CMAKE_USE_PTHREADS_INIT)
+find_package(BISON 2.5 REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(UECC REQUIRED libuecc>=3)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 792d9cb..ad92508 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,5 +1,5 @@
-set_directory_properties(PROPERTIES COMPILE_DEFINITIONS _GNU_SOURCE)
-set(FASTD_CFLAGS "-pthread -std=c99 ${UECC_CFLAGS_OTHER} ${NACL_CFLAGS_OTHER} ${OPENSSL_CRYPTO_CFLAGS_OTHER} ${CFLAGS_LTO} -Wall")
+set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE __APPLE_USE_RFC_3542)
+set(FASTD_CFLAGS "${PTHREAD_CFLAGS} -std=c99 ${UECC_CFLAGS_OTHER} ${NACL_CFLAGS_OTHER} ${OPENSSL_CRYPTO_CFLAGS_OTHER} ${CFLAGS_LTO} -Wall")
include_directories(${FASTD_SOURCE_DIR} ${FASTD_BINARY_DIR}/src)
link_directories(${UECC_LIBRARY_DIRS} ${NACL_LIBRARY_DIRS} ${OPENSSL_CRYPTO_LIBRARY_DIRS})
@@ -43,7 +43,7 @@ add_executable(fastd
${BISON_fastd_config_parse_OUTPUTS}
)
set_property(TARGET fastd PROPERTY COMPILE_FLAGS "${FASTD_CFLAGS}")
-set_property(TARGET fastd PROPERTY LINK_FLAGS "-pthread ${UECC_LDFLAGS_OTHER} ${NACL_LDFLAGS_OTHER} ${OPENSSL_CRYPTO_LDFLAGS_OTHER} ${LDFLAGS_LTO}")
+set_property(TARGET fastd PROPERTY LINK_FLAGS "${PTHREAD_LDFLAGS} ${UECC_LDFLAGS_OTHER} ${NACL_LDFLAGS_OTHER} ${OPENSSL_CRYPTO_LDFLAGS_OTHER} ${LDFLAGS_LTO}")
set_property(TARGET fastd APPEND PROPERTY INCLUDE_DIRECTORIES ${CAP_INCLUDE_DIR} ${NACL_INCLUDE_DIRS})
target_link_libraries(fastd protocols methods ciphers macs ${RT_LIBRARY} ${CAP_LIBRARY} ${UECC_LIBRARIES} ${NACL_LIBRARIES} ${OPENSSL_CRYPTO_LIBRARIES})
diff --git a/src/compat.h b/src/compat.h
index af7264d..c73a340 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -35,6 +35,7 @@
#include <fastd_config.h>
#include <stdint.h>
+#include <time.h>
#include <unistd.h>
#include <sys/types.h>
@@ -80,12 +81,20 @@ struct ethhdr {
#endif
+/** The type of the third parameter of getgrouplist */
+#ifdef __APPLE__
+#define GROUPLIST_TYPE int
+#else
+#define GROUPLIST_TYPE gid_t
+#endif
+
+
#ifndef HAVE_GET_CURRENT_DIR_NAME
/** Replacement function for *BSD systems not supporting get_current_dir_name() */
static inline char *get_current_dir_name(void) {
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
return getcwd(NULL, 0);
@@ -98,3 +107,28 @@ static inline char *get_current_dir_name(void) {
}
#endif
+
+
+#ifdef __APPLE__
+
+#include <mach/mach_time.h>
+
+#define CLOCK_MONOTONIC 0
+#define clockid_t int
+
+static inline int clock_gettime(clockid_t clk_id __attribute__((unused)), struct timespec *tp) {
+ static mach_timebase_info_data_t timebase_info = {};
+
+ if (!timebase_info.denom)
+ mach_timebase_info(&timebase_info);
+
+ uint64_t time = (((long double)mach_absolute_time())*timebase_info.numer) / timebase_info.denom;
+
+ tp->tv_sec = time / 1000000000;
+ tp->tv_nsec = time % 1000000000;
+
+ return 0;
+}
+
+
+#endif
diff --git a/src/config.c b/src/config.c
index f2a6dab..18ef34c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -439,11 +439,17 @@ static void configure_user(void) {
if (getgrouplist(conf.user, conf.gid, NULL, &ngroups) < 0) {
/* the user has supplementary groups */
- conf.groups = fastd_new0_array(ngroups, gid_t);
- if (getgrouplist(conf.user, conf.gid, conf.groups, &ngroups) < 0)
+ GROUPLIST_TYPE groups[ngroups];
+
+ if (getgrouplist(conf.user, conf.gid, groups, &ngroups) < 0)
exit_errno("getgrouplist");
conf.n_groups = ngroups;
+ conf.groups = fastd_new_array(ngroups, gid_t);
+
+ int i;
+ for (i = 0; i < ngroups; i++)
+ conf.groups[i] = groups[i];
}
}
}
diff --git a/src/fastd_config.h.in b/src/fastd_config.h.in
index 2057be1..ba57aca 100644
--- a/src/fastd_config.h.in
+++ b/src/fastd_config.h.in
@@ -48,6 +48,9 @@
/** Defined if the platform supports epoll */
#cmakedefine USE_EPOLL
+/** Defined if the platform uses select instead of poll */
+#cmakedefine USE_SELECT
+
/** Defined if the platform supports SO_FREEBIND */
#cmakedefine USE_FREEBIND
diff --git a/src/poll.c b/src/poll.c
index db3e27e..a0b41ba 100644
--- a/src/poll.c
+++ b/src/poll.c
@@ -43,6 +43,12 @@
#endif
+#ifdef USE_SELECT
+
+#include <sys/select.h>
+
+#endif
+
/** Returns the time to the next handshake or -1 */
static inline int handshake_timeout(void) {
@@ -236,6 +242,8 @@ void fastd_poll_delete_peer(size_t i) {
void fastd_poll_handle(void) {
+ size_t i;
+
int maintenance_timeout = timespec_diff(&ctx.next_maintenance, &ctx.now);
if (maintenance_timeout < 0)
@@ -252,14 +260,63 @@ void fastd_poll_handle(void) {
sigemptyset(&set);
pthread_sigmask(SIG_SETMASK, &set, &oldset);
- int ret = poll(VECTOR_DATA(ctx.pollfds), VECTOR_LEN(ctx.pollfds), timeout);
+ int ret = 0;
+
+#ifdef USE_SELECT
+ /* Inefficient implementation for OSX... */
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ int maxfd = -1;
+
+ for (i = 0; i < VECTOR_LEN(ctx.pollfds); i++) {
+ struct pollfd *pollfd = &VECTOR_INDEX(ctx.pollfds, i);
+ if (pollfd->fd >= 0) {
+ FD_SET(pollfd->fd, &readfds);
+
+ if (pollfd->fd > maxfd)
+ maxfd = pollfd->fd;
+ }
+ }
+
+ fd_set errfds = readfds;
+
+ if (maxfd >= 0) {
+ struct timeval tv = {}, *tvp = NULL;
+ if (timeout >= 0) {
+ tvp = &tv;
+ tv.tv_sec = timeout/1000;
+ tv.tv_usec = (timeout%1000)*1000;
+ }
+ ret = select(maxfd+1, &readfds, NULL, &errfds, tvp);
+ if (ret < 0 && errno != EINTR)
+ exit_errno("select");
+ }
+
+ if (ret > 0) {
+ for (i = 0; i < VECTOR_LEN(ctx.pollfds); i++) {
+ struct pollfd *pollfd = &VECTOR_INDEX(ctx.pollfds, i);
+ pollfd->revents = 0;
+
+ if (pollfd->fd < 0)
+ continue;
+
+ if (FD_ISSET(pollfd->fd, &readfds))
+ pollfd->revents |= POLLIN;
+ if (FD_ISSET(pollfd->fd, &errfds))
+ pollfd->revents |= POLLERR;
+ }
+ }
+
+#else
+ ret = poll(VECTOR_DATA(ctx.pollfds), VECTOR_LEN(ctx.pollfds), timeout);
if (ret < 0 && errno != EINTR)
exit_errno("poll");
+#endif
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
fastd_update_time();
- if (ret < 0)
+ if (ret <= 0)
return;
if (VECTOR_INDEX(ctx.pollfds, 0).revents & POLLIN)
@@ -267,7 +324,6 @@ void fastd_poll_handle(void) {
if (VECTOR_INDEX(ctx.pollfds, 1).revents & POLLIN)
fastd_async_handle();
- size_t i;
for (i = 0; i < ctx.n_socks; i++) {
if (VECTOR_INDEX(ctx.pollfds, 2+i).revents & (POLLERR|POLLHUP|POLLNVAL)) {
fastd_socket_error(&ctx.socks[i]);
diff --git a/src/tuntap.c b/src/tuntap.c
index fce0619..6281405 100644
--- a/src/tuntap.c
+++ b/src/tuntap.c
@@ -42,7 +42,9 @@
#else
+#ifndef __APPLE__
#include <net/if_tun.h>
+#endif
#ifdef __FreeBSD__
#include <net/if_tap.h>
@@ -52,7 +54,7 @@
/** Defines if the platform uses an address family header on TUN interfaces */
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
static const bool multiaf_tun = false;
#else
static const bool multiaf_tun = true;
@@ -294,6 +296,57 @@ void fastd_tuntap_open(void) {
#endif
+#elif __APPLE__
+
+/** Opens the TUN/TAP device */
+void fastd_tuntap_open(void) {
+ const char *devtype;
+ switch (conf.mode) {
+ case MODE_TAP:
+ devtype = "tap";
+ break;
+
+ case MODE_TUN:
+ devtype = "tun";
+ break;
+
+ default:
+ exit_bug("invalid mode");
+ }
+
+ char ifname[5+IFNAMSIZ] = "/dev/";
+ if (!conf.ifname)
+ exit_error("config error: no interface name given.");
+ else if (strncmp(conf.ifname, devtype, 3) != 0)
+ exit_error("config error: `%s' doesn't seem to be a %s device", conf.ifname, devtype);
+ else
+ strncat(ifname, conf.ifname, IFNAMSIZ-1);
+
+ pr_debug("initializing tun device...");
+
+ if ((ctx.tunfd = open(ifname, O_RDWR|O_NONBLOCK)) < 0)
+ exit_errno("could not open tun device file");
+
+ ctx.ifname = fastd_strndup(conf.ifname, IFNAMSIZ-1);
+
+ int ctl_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (ctl_sock < 0)
+ exit_errno("socket");
+
+ struct ifreq ifr = {};
+ strncpy(ifr.ifr_name, conf.ifname, IFNAMSIZ-1);
+ ifr.ifr_mtu = conf.mtu;
+ if (ioctl(ctl_sock, SIOCSIFMTU, &ifr) < 0)
+ exit_errno("SIOCSIFMTU ioctl failed");
+
+ if (close(ctl_sock))
+ pr_error_errno("close");
+
+ fastd_poll_set_fd_tuntap();
+
+ pr_debug("tun device initialized.");
+}
+
#else
#error unknown tun/tap implementation
@@ -348,7 +401,7 @@ void fastd_tuntap_write(fastd_buffer_t buffer) {
}
if (write(ctx.tunfd, buffer.data, buffer.len) < 0)
- pr_warn_errno("write");
+ pr_debug2_errno("write");
}
/** Closes the TUN/TAP device */