From 96a291d11f884b18356ba8ef4b12b82d658d8d04 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 1 Aug 2014 19:17:57 -0700 Subject: Add support for Mac OS X --- src/CMakeLists.txt | 6 ++--- src/compat.h | 36 +++++++++++++++++++++++++++++- src/config.c | 10 +++++++-- src/fastd_config.h.in | 3 +++ src/poll.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/tuntap.c | 57 ++++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 163 insertions(+), 11 deletions(-) (limited to 'src') 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 #include +#include #include #include @@ -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 + +#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 + +#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 +#endif #ifdef __FreeBSD__ #include @@ -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 */ -- cgit v1.2.3