From 7ae3d85c7249b9e8846bc87fdf44e8621a370565 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Thu, 17 Aug 2017 14:02:34 +0200 Subject: ipcpd: Support Berkeley Packet Filter in LLC shim This adds support reading Ethernet frames using the Berkeley Packet Filter (BPF). Ouroboros now fully runs on OS X Sierra. --- include/ouroboros/config.h.in | 11 +- src/ipcpd/CMakeLists.txt | 4 +- src/ipcpd/shim-eth-llc/CMakeLists.txt | 63 ++++--- src/ipcpd/shim-eth-llc/main.c | 330 +++++++++++++++++++++------------- 4 files changed, 260 insertions(+), 148 deletions(-) diff --git a/include/ouroboros/config.h.in b/include/ouroboros/config.h.in index b9702171..d5871624 100644 --- a/include/ouroboros/config.h.in +++ b/include/ouroboros/config.h.in @@ -31,6 +31,10 @@ #ifdef __FreeBSD__ #define __BSD_VISIBLE 1 #endif +#ifdef __APPLE__ +#define _BSD_SOURCE +#define _DARWIN_C_SOURCE +#endif #define IPCP_SHIM_UDP_EXEC "@IPCP_SHIM_UDP_TARGET@" #define IPCP_SHIM_ETH_LLC_EXEC "@IPCP_SHIM_ETH_LLC_TARGET@" #define IPCP_NORMAL_EXEC "@IPCP_NORMAL_TARGET@" @@ -40,6 +44,7 @@ #cmakedefine HAVE_LIBGCRYPT #cmakedefine HAVE_OPENSSL #cmakedefine HAVE_NETMAP +#cmakedefine HAVE_BPF #define AP_MAX_FLOWS 2048 #define AP_RES_FDS 64 #define AP_MAX_FQUEUES 64 @@ -60,9 +65,13 @@ /* IPCP dynamic threadpooling */ #define IPCP_MIN_THREADS 4 #define IPCP_ADD_THREADS 16 -#define IPCP_SCHED_THREADS 8 +#define IPCP_SCHED_THREADS 2 #define IPCPD_MAX_CONNS IRMD_MAX_FLOWS +#ifdef __APPLE__ +#define PTHREAD_COND_CLOCK CLOCK_REALTIME +#else #define PTHREAD_COND_CLOCK CLOCK_MONOTONIC +#endif #define PFT_SIZE 1 << 12 /* Timeout values */ #define IRMD_ACCEPT_TIMEOUT 100 diff --git a/src/ipcpd/CMakeLists.txt b/src/ipcpd/CMakeLists.txt index 2e8bda23..0ead1fed 100644 --- a/src/ipcpd/CMakeLists.txt +++ b/src/ipcpd/CMakeLists.txt @@ -8,7 +8,7 @@ set(IPCP_SOURCES add_subdirectory(local) add_subdirectory(normal) add_subdirectory(shim-udp) -if (NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL GNU) - add_subdirectory(shim-eth-llc) +add_subdirectory(shim-eth-llc) +if (NOT APPLE) add_subdirectory(tests) endif () diff --git a/src/ipcpd/shim-eth-llc/CMakeLists.txt b/src/ipcpd/shim-eth-llc/CMakeLists.txt index 12bfb42e..21003cf0 100644 --- a/src/ipcpd/shim-eth-llc/CMakeLists.txt +++ b/src/ipcpd/shim-eth-llc/CMakeLists.txt @@ -17,31 +17,54 @@ find_path(NETMAP_C_INCLUDE_DIR HINTS /usr/include /usr/local/include ) -protobuf_generate_c(SHIM_ETH_LLC_PROTO_SRCS SHIM_ETH_LLC_PROTO_HDRS - shim_eth_llc_messages.proto) - -set(IPCP_SHIM_ETH_LLC_TARGET ipcpd-shim-eth-llc - CACHE STRING "IPCP_SHIM_ETH_LLC_TARGET") - -set(SHIM_ETH_LLC_SOURCES - # Add source files here - ${CMAKE_CURRENT_SOURCE_DIR}/main.c) +find_path(BPF_C_INCLUDE_DIR + net/bpf.h + HINTS /usr/include /usr/local/include + ) -add_executable(ipcpd-shim-eth-llc ${SHIM_ETH_LLC_SOURCES} ${IPCP_SOURCES} - ${SHIM_ETH_LLC_PROTO_SRCS}) -target_link_libraries(ipcpd-shim-eth-llc LINK_PUBLIC ouroboros - ${PROTOBUF_C_LIBRARY}) +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux" AND + NOT BPF_C_INCLUDE_DIR STREQUAL "BPF_C_INCLUDE_DIR-NOTFOUND") + message(STATUS "Found Berkeley Packet Filter headers in ${BPF_C_INCLUDE_DIR}") + set(HAVE_BPF "1" CACHE STRING "Have Berkeley Packet Filter") +endif () -if (NOT ${NETMAP_C_INCLUDE_DIR} STREQUAL "NETMAP_C_INCLUDE_DIR-NOTFOUND") +if (NOT NETMAP_C_INCLUDE_DIR STREQUAL "NETMAP_C_INCLUDE_DIR-NOTFOUND") message(STATUS "Found netmap headers in ${NETMAP_C_INCLUDE_DIR}") - include_directories(${NETMAP_C_INCLUDE_DIR}) set(HAVE_NETMAP "1" CACHE STRING "Have netmap") test_and_set_c_compiler_flag_global(-std=c99) endif () -include(AddCompileFlags) -if (CMAKE_BUILD_TYPE MATCHES Debug) - add_compile_flags(ipcpd-shim-eth-llc -DCONFIG_OUROBOROS_DEBUG) -endif (CMAKE_BUILD_TYPE MATCHES Debug) +if (HAVE_NETMAP OR HAVE_BPF OR CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(STATUS "Supported raw Ethernet API found, building shim-eth-llc") + protobuf_generate_c(SHIM_ETH_LLC_PROTO_SRCS SHIM_ETH_LLC_PROTO_HDRS + shim_eth_llc_messages.proto) + + set(SHIM_ETH_LLC_SOURCES + # Add source files here + ${CMAKE_CURRENT_SOURCE_DIR}/main.c + ) + + set(IPCP_SHIM_ETH_LLC_TARGET ipcpd-shim-eth-llc + CACHE STRING "IPCP_SHIM_ETH_LLC_TARGET") + + add_executable(ipcpd-shim-eth-llc ${SHIM_ETH_LLC_SOURCES} ${IPCP_SOURCES} + ${SHIM_ETH_LLC_PROTO_SRCS}) + + if (HAVE_BPF AND NOT APPLE) + target_include_directories(ipcpd-shim-eth-llc PUBLIC ${BPF_C_INCLUDE_DIR}) + endif () + + if (HAVE_NETMAP AND NOT APPLE) + target_include_directories(ipcpd-shim-eth-llc PUBLIC ${NETMAP_C_INCLUDE_DIR}) + endif () -install(TARGETS ipcpd-shim-eth-llc RUNTIME DESTINATION sbin) + target_link_libraries(ipcpd-shim-eth-llc LINK_PUBLIC ouroboros + ${PROTOBUF_C_LIBRARY}) + + include(AddCompileFlags) + if (CMAKE_BUILD_TYPE MATCHES Debug) + add_compile_flags(ipcpd-shim-eth-llc -DCONFIG_OUROBOROS_DEBUG) + endif (CMAKE_BUILD_TYPE MATCHES Debug) + + install(TARGETS ipcpd-shim-eth-llc RUNTIME DESTINATION sbin) +endif () diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index 6d8d0895..55406a00 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -20,8 +20,6 @@ * Foundation, Inc., http://www.fsf.org/about/contact/. */ -#define _DEFAULT_SOURCE - #define OUROBOROS_PREFIX "ipcpd/shim-eth-llc" #include @@ -39,7 +37,6 @@ #include "ipcp.h" #include "shim_eth_llc_messages.pb-c.h" -#include #include #include #include @@ -49,6 +46,8 @@ #include #include #include + +#include #include #ifdef __linux__ @@ -62,29 +61,37 @@ #include #endif +#ifdef __APPLE__ +#include +#include +#endif + #include #include -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) #define NETMAP_WITH_LIBS #include +#elif defined(HAVE_BPF) +#define BPF_DEV_MAX 256 +#define BPF_BLEN sysconf(_SC_PAGESIZE) +#include #endif -typedef ShimEthLlcMsg shim_eth_llc_msg_t; - -#define THIS_TYPE IPCP_SHIM_ETH_LLC -#define MGMT_SAP 0x01 -#define MAC_SIZE 6 -#define LLC_HEADER_SIZE 3 -#define MAX_SAPS 64 -#define ETH_HEADER_SIZE (2 * MAC_SIZE + 2) -#define ETH_FRAME_SIZE (ETH_HEADER_SIZE + LLC_HEADER_SIZE \ - + SHIM_ETH_LLC_MAX_SDU_SIZE) +#define THIS_TYPE IPCP_SHIM_ETH_LLC +#define MGMT_SAP 0x01 +#define MAC_SIZE 6 +#define LLC_HEADER_SIZE 3 +#define MAX_SAPS 64 +#define ETH_HEADER_SIZE (2 * MAC_SIZE + 2) +#define ETH_FRAME_SIZE (ETH_HEADER_SIZE + LLC_HEADER_SIZE \ + + SHIM_ETH_LLC_MAX_SDU_SIZE) #define SHIM_ETH_LLC_MAX_SDU_SIZE (1500 - LLC_HEADER_SIZE) +#define EVENT_WAIT_TIMEOUT 10000 /* us */ +#define NAME_QUERY_TIMEOUT 2000 /* ms */ +#define MGMT_TIMEOUT 100 /* ms */ -#define EVENT_WAIT_TIMEOUT 100 /* us */ -#define NAME_QUERY_TIMEOUT 2000 /* ms */ -#define MGMT_TIMEOUT 100 /* ms */ +typedef ShimEthLlcMsg shim_eth_llc_msg_t; struct eth_llc_frame { uint8_t dst_hwaddr[MAC_SIZE]; @@ -110,18 +117,17 @@ struct mgmt_frame { }; struct { -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) struct nm_desc * nmd; uint8_t hw_addr[MAC_SIZE]; struct pollfd poll_in; struct pollfd poll_out; -#else +#elif defined(HAVE_BPF) + int bpf; + uint8_t hw_addr[MAC_SIZE]; +#elif defined __linux__ int s_fd; - #ifdef __FreeBSD__ - struct sockaddr_dl device; - #else struct sockaddr_ll device; - #endif #endif /* HAVE_NETMAP */ struct bmp * saps; @@ -145,36 +151,28 @@ struct { static int eth_llc_data_init(void) { int i; - int ret = -1; + int ret = -ENOMEM; pthread_condattr_t cattr; eth_llc_data.fd_to_ef = malloc(sizeof(struct ef) * IRMD_MAX_FLOWS); if (eth_llc_data.fd_to_ef == NULL) - return -ENOMEM; + goto fail_fd_to_ef; eth_llc_data.ef_to_fd = malloc(sizeof(struct ef) * MAX_SAPS); - if (eth_llc_data.ef_to_fd == NULL) { - ret = -ENOMEM; - goto free_fd_to_ef; - } + if (eth_llc_data.ef_to_fd == NULL) + goto fail_ef_to_fd; eth_llc_data.saps = bmp_create(MAX_SAPS, 2); - if (eth_llc_data.saps == NULL) { - ret = -ENOMEM; - goto free_ef_to_fd; - } + if (eth_llc_data.saps == NULL) + goto fail_saps; eth_llc_data.np1_flows = flow_set_create(); - if (eth_llc_data.np1_flows == NULL) { - ret = -ENOMEM; - goto bmp_destroy; - } + if (eth_llc_data.np1_flows == NULL) + goto fail_np1_flows; eth_llc_data.fq = fqueue_create(); - if (eth_llc_data.fq == NULL) { - ret = -ENOMEM; - goto flow_set_destroy; - } + if (eth_llc_data.fq == NULL) + goto fail_fq; for (i = 0; i < MAX_SAPS; ++i) eth_llc_data.ef_to_fd[i] = -1; @@ -185,49 +183,56 @@ static int eth_llc_data_init(void) memset(ð_llc_data.fd_to_ef[i].r_addr, 0, MAC_SIZE); } + ret = -1; + if (pthread_rwlock_init(ð_llc_data.flows_lock, NULL)) - goto fqueue_destroy; + goto fail_flows_lock; if (pthread_mutex_init(ð_llc_data.mgmt_lock, NULL)) - goto flow_lock_destroy; + goto fail_mgmt_lock; if (pthread_condattr_init(&cattr)) - goto mgmt_lock_destroy;; + goto fail_condattr; #ifndef __APPLE__ pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK); #endif if (pthread_cond_init(ð_llc_data.mgmt_cond, &cattr)) - goto mgmt_lock_destroy; + goto fail_mgmt_cond; + + pthread_condattr_destroy(&cattr); list_head_init(ð_llc_data.mgmt_frames); return 0; - - mgmt_lock_destroy: + fail_mgmt_cond: + pthread_condattr_destroy(&cattr); + fail_condattr: pthread_mutex_destroy(ð_llc_data.mgmt_lock); - flow_lock_destroy: + fail_mgmt_lock: pthread_rwlock_destroy(ð_llc_data.flows_lock); - fqueue_destroy: + fail_flows_lock: fqueue_destroy(eth_llc_data.fq); - flow_set_destroy: + fail_fq: flow_set_destroy(eth_llc_data.np1_flows); - bmp_destroy: + fail_np1_flows: bmp_destroy(eth_llc_data.saps); - free_ef_to_fd: + fail_saps: free(eth_llc_data.ef_to_fd); - free_fd_to_ef: + fail_ef_to_fd: free(eth_llc_data.fd_to_ef); - + fail_fd_to_ef: return ret; } void eth_llc_data_fini(void) { -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) nm_close(eth_llc_data.nmd); -#else +#elif defined(HAVE_BPF) + close(eth_llc_data.bpf); +#elif defined(__linux__) close(eth_llc_data.s_fd); #endif pthread_cond_destroy(ð_llc_data.mgmt_cond); @@ -273,11 +278,9 @@ static int eth_llc_ipcp_send_frame(const uint8_t * dst_addr, memcpy(llc_frame->dst_hwaddr, dst_addr, MAC_SIZE); memcpy(llc_frame->src_hwaddr, -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) || defined(HAVE_BPF) eth_llc_data.hw_addr, -#elif defined ( __FreeBSD__ ) - LLADDR(ð_llc_data.device), -#else +#elif defined(__linux__) eth_llc_data.device.sll_addr, #endif /* HAVE_NETMAP */ MAC_SIZE); @@ -289,22 +292,28 @@ static int eth_llc_ipcp_send_frame(const uint8_t * dst_addr, memcpy(&llc_frame->payload, payload, len); frame_len = ETH_HEADER_SIZE + LLC_HEADER_SIZE + len; -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) if (poll(ð_llc_data.poll_out, 1, -1) < 0) return -1; if (nm_inject(eth_llc_data.nmd, frame, frame_len) != (int) frame_len) { - log_err("Failed to send message."); + log_dbg("Failed to send message."); return -1; } -#else +#elif defined(HAVE_BPF) + if (write(eth_llc_data.bpf, frame, frame_len) < 0) { + log_dbg("Failed to send message."); + return -1; + } + +#elif defined(__linux__) if (sendto(eth_llc_data.s_fd, frame, frame_len, 0, (struct sockaddr *) ð_llc_data.device, sizeof(eth_llc_data.device)) <= 0) { - log_err("Failed to send message."); + log_dbg("Failed to send message."); return -1; } #endif /* HAVE_NETMAP */ @@ -381,7 +390,7 @@ static int eth_llc_ipcp_sap_req(uint8_t r_sap, const uint8_t * dst, qoscube_t cube) { - struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 1000}; + struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 100}; struct timespec abstime; int fd; @@ -489,6 +498,7 @@ static int eth_llc_ipcp_name_query_reply(const uint8_t * hash, shim_data_dir_add_entry(ipcpi.shim_data, hash, address); pthread_mutex_lock(&ipcpi.shim_data->dir_queries_lock); + list_for_each(pos, &ipcpi.shim_data->dir_queries) { struct dir_query * e = list_entry(pos, struct dir_query, next); @@ -496,6 +506,7 @@ static int eth_llc_ipcp_name_query_reply(const uint8_t * hash, shim_data_dir_query_respond(e); } } + pthread_mutex_unlock(&ipcpi.shim_data->dir_queries_lock); return 0; @@ -598,17 +609,17 @@ static void * eth_llc_ipcp_sdu_reader(void * o) uint8_t dsap; uint8_t ssap; int fd; -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) uint8_t * buf; -#else + struct nm_pkthdr hdr; +#elif defined(HAVE_BPF) + uint8_t buf[BPF_BLEN]; +#elif defined(__linux__) uint8_t buf[ETH_FRAME_SIZE]; #endif int frame_len = 0; struct eth_llc_frame * llc_frame; struct mgmt_frame * frame; -#ifdef HAVE_NETMAP - struct nm_pkthdr hdr; -#endif (void) o; @@ -617,8 +628,8 @@ static void * eth_llc_ipcp_sdu_reader(void * o) while (true) { if (ipcp_get_state() != IPCP_OPERATIONAL) return (void *) 0; -#ifdef HAVE_NETMAP - if (poll(ð_llc_data.poll_in, 1, EVENT_WAIT_TIMEOUT) < 0) +#if defined(HAVE_NETMAP) + if (poll(ð_llc_data.poll_in, 1, EVENT_WAIT_TIMEOUT / 1000) < 0) continue; if (eth_llc_data.poll_in.revents == 0) /* TIMED OUT */ continue; @@ -628,28 +639,34 @@ static void * eth_llc_ipcp_sdu_reader(void * o) log_err("Bad read from netmap device."); continue; } -#else +#elif defined(HAVE_BPF) + frame_len = read(eth_llc_data.bpf, buf, BPF_BLEN); +#elif defined(__linux__) frame_len = recv(eth_llc_data.s_fd, buf, SHIM_ETH_LLC_MAX_SDU_SIZE, 0); #endif - if (frame_len < 0) + if (frame_len <= 0) continue; +#if defined(HAVE_BPF) && !defined(HAVE_NETMAP) + llc_frame = (struct eth_llc_frame *) + (buf + ((struct bpf_hdr *) buf)->bh_hdrlen); +#else llc_frame = (struct eth_llc_frame *) buf; - +#endif assert(llc_frame->dst_hwaddr); -#ifdef HAVE_NETMAP + +#if !defined(HAVE_BPF) + #if defined(HAVE_NETMAP) if (memcmp(eth_llc_data.hw_addr, -#elif defined ( __FreeBSD__ ) - if (memcmp(LLADDR(ð_llc_data.device), -#else + #elif defined(__linux__) if (memcmp(eth_llc_data.device.sll_addr, -#endif /* HAVE_NETMAP */ + #endif /* HAVE_NETMAP */ llc_frame->dst_hwaddr, MAC_SIZE) && - memcmp(br_addr, llc_frame->dst_hwaddr, MAC_SIZE)) - continue; - + memcmp(br_addr, llc_frame->dst_hwaddr, MAC_SIZE)) { + } +#endif memcpy(&length, &llc_frame->length, sizeof(length)); length = ntohs(length); @@ -744,20 +761,45 @@ static void * eth_llc_ipcp_sdu_writer(void * o) return (void *) 1; } +#if defined (HAVE_BPF) && !defined(HAVE_NETMAP) +static int open_bpf_device(void) +{ + char dev[32]; + size_t i = 0; + + for (i = 0; i < BPF_DEV_MAX; i++) { + int fd = -1; + + snprintf(dev, sizeof(dev), "/dev/bpf%zu", i); + + fd = open(dev, O_RDWR); + if (fd > -1) + return fd; + } + + return -1; +} +#endif + static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) { int idx; struct ifreq ifr; -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) char ifn[IFNAMSIZ]; -#else - struct timeval tv = {0, EVENT_WAIT_TIMEOUT * 1000}; +#elif defined(HAVE_BPF) + int enable = 1; + int disable = 0; + int blen; + struct timeval tv = {0, EVENT_WAIT_TIMEOUT}; +#elif defined(__linux__) + struct timeval tv = {0, EVENT_WAIT_TIMEOUT}; #endif /* HAVE_NETMAP */ -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__APPLE__) struct ifaddrs * ifaddr; struct ifaddrs * ifa; -#else +#elif defined(__linux__) int skfd; #endif assert(conf); @@ -771,7 +813,7 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) memset(&ifr, 0, sizeof(ifr)); memcpy(ifr.ifr_name, conf->if_name, strlen(conf->if_name)); -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__APPLE__) if (getifaddrs(&ifaddr) < 0) { log_err("Could not get interfaces."); return -1; @@ -781,7 +823,12 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) if (strcmp(ifa->ifa_name, conf->if_name)) continue; log_dbg("Interface %s found.", conf->if_name); + + #if defined(HAVE_NETMAP) || defined(HAVE_BPF) + memcpy(eth_llc_data.hw_addr, LLADDR((struct sockaddr_dl *)(ifa)->ifa_addr), MAC_SIZE); + #else memcpy(&ifr.ifr_addr, ifa->ifa_addr, sizeof(*ifa->ifa_addr)); + #endif break; } @@ -792,7 +839,7 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) } freeifaddrs(ifaddr); -#else +#elif defined(__linux__) skfd = socket(AF_UNIX, SOCK_STREAM, 0); if (skfd < 0) { log_err("Failed to open socket."); @@ -815,14 +862,10 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) } #endif /* __FreeBSD__ */ -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP) strcpy(ifn, "netmap:"); strcat(ifn, conf->if_name); - #ifdef __FreeBSD__ - memcpy(eth_llc_data.hw_addr, ifr.ifr_addr.sa_data, MAC_SIZE); - #else - memcpy(eth_llc_data.hw_addr, ifr.ifr_hwaddr.sa_data, MAC_SIZE); - #endif /* __FreeBSD__ */ + eth_llc_data.nmd = nm_open(ifn, NULL, 0, NULL); if (eth_llc_data.nmd == NULL) { log_err("Failed to open netmap device."); @@ -838,17 +881,54 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) eth_llc_data.poll_out.events = POLLOUT; log_info("Using netmap device."); -#else /* !HAVE_NETMAP */ +#elif defined(HAVE_BPF) /* !HAVE_NETMAP */ + eth_llc_data.bpf = open_bpf_device(); + if (eth_llc_data.bpf < 0) { + log_err("Failed to open bpf device."); + return -1; + } + + ioctl(eth_llc_data.bpf, BIOCGBLEN, &blen); + if (BPF_BLEN < blen) { + log_err("BPF buffer too small (is: %ld must be: %d).", + BPF_BLEN, blen); + close(eth_llc_data.bpf); + return -1; + } + + if (ioctl(eth_llc_data.bpf, BIOCSETIF, &ifr) < 0) { + log_err("Failed to set interface."); + close(eth_llc_data.bpf); + return -1; + } + + if (ioctl(eth_llc_data.bpf, BIOCSHDRCMPLT, &enable) < 0) { + log_err("Failed to set BIOCSHDRCMPLT."); + close(eth_llc_data.bpf); + return -1; + } + + if (ioctl(eth_llc_data.bpf, BIOCSSEESENT, &disable) < 0) { + log_err("Failed to set BIOCSSEESENT."); + close(eth_llc_data.bpf); + return -1; + } + + if (ioctl(eth_llc_data.bpf, BIOCSRTIMEOUT, &tv) < 0) { + log_err("Failed to set BIOCSRTIMEOUT."); + close(eth_llc_data.bpf); + return -1; + } + + if (ioctl(eth_llc_data.bpf, BIOCIMMEDIATE, &enable) < 0) { + log_err("Failed to set BIOCIMMEDIATE."); + close(eth_llc_data.bpf); + return -1; + } + + log_info("Using Berkeley Packet Filter."); +#elif defined(__linux__) memset(&(eth_llc_data.device), 0, sizeof(eth_llc_data.device)); - #ifdef __FreeBSD__ - eth_llc_data.device.sdl_index = idx; - eth_llc_data.device.sdl_family = AF_LINK; - memcpy(LLADDR(ð_llc_data.device), ifr.ifr_addr.sa_data, MAC_SIZE); - eth_llc_data.device.sdl_alen = MAC_SIZE; - eth_llc_data.s_fd = socket(AF_LINK, SOCK_RAW, 0); - - log_info("Using berkeley packet filter."); /* TODO */ - #else eth_llc_data.device.sll_ifindex = idx; eth_llc_data.device.sll_family = AF_PACKET; memcpy(eth_llc_data.device.sll_addr, ifr.ifr_hwaddr.sa_data, MAC_SIZE); @@ -857,7 +937,6 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) eth_llc_data.s_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_802_2)); log_info("Using raw socket device."); - #endif /* __FreeBSD__ */ if (eth_llc_data.s_fd < 0) { log_err("Failed to create socket."); @@ -872,8 +951,8 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) } if (setsockopt(eth_llc_data.s_fd, SOL_SOCKET, SO_RCVTIMEO, - (void *) &tv, sizeof(tv))) { - log_err("Failed to set socket timeout."); + &tv, sizeof(tv))) { + log_err("Failed to set socket timeout: %s.", strerror(errno)); close(eth_llc_data.s_fd); return -1; } @@ -1027,7 +1106,7 @@ static int eth_llc_ipcp_flow_alloc(int fd, static int eth_llc_ipcp_flow_alloc_resp(int fd, int response) { - struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 1000}; + struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 100}; struct timespec abstime; uint8_t ssap = 0; uint8_t r_sap = 0; @@ -1126,33 +1205,23 @@ static struct ipcp_ops eth_llc_ops = { int main(int argc, char * argv[]) { - if (ipcp_init(argc, argv, THIS_TYPE, ð_llc_ops) < 0) { - ipcp_create_r(getpid(), -1); - exit(EXIT_FAILURE); - } + if (ipcp_init(argc, argv, THIS_TYPE, ð_llc_ops) < 0) + goto fail_init; if (eth_llc_data_init() < 0) { log_err("Failed to init shim-eth-llc data."); - ipcp_create_r(getpid(), -1); - ipcp_fini(); - exit(EXIT_FAILURE); + goto fail_data_init; } if (ipcp_boot() < 0) { log_err("Failed to boot IPCP."); - ipcp_create_r(getpid(), -1); - eth_llc_data_fini(); - ipcp_fini(); - exit(EXIT_FAILURE); + goto fail_boot; } if (ipcp_create_r(getpid(), 0)) { log_err("Failed to notify IRMd we are initialized."); ipcp_set_state(IPCP_NULL); - ipcp_shutdown(); - eth_llc_data_fini(); - ipcp_fini(); - exit(EXIT_FAILURE); + goto fail_create_r; } ipcp_shutdown(); @@ -1168,4 +1237,15 @@ int main(int argc, ipcp_fini(); exit(EXIT_SUCCESS); + + fail_create_r: + ipcp_shutdown(); + fail_boot: + eth_llc_data_fini(); + fail_data_init: + ipcp_fini(); + fail_init: + ipcp_create_r(getpid(), -1); + exit(EXIT_FAILURE); + } -- cgit v1.2.3