diff options
Diffstat (limited to 'src/ipcpd')
| -rw-r--r-- | src/ipcpd/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/ipcpd/shim-eth-llc/CMakeLists.txt | 63 | ||||
| -rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 330 | 
3 files changed, 250 insertions, 147 deletions
| 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 <ouroboros/config.h> @@ -39,7 +37,6 @@  #include "ipcp.h"  #include "shim_eth_llc_messages.pb-c.h" -#include <net/if.h>  #include <signal.h>  #include <stdlib.h>  #include <pthread.h> @@ -49,6 +46,8 @@  #include <sys/socket.h>  #include <sys/types.h>  #include <sys/ioctl.h> + +#include <net/if.h>  #include <netinet/in.h>  #ifdef __linux__ @@ -62,29 +61,37 @@  #include <ifaddrs.h>  #endif +#ifdef __APPLE__ +#include <net/if_dl.h> +#include <ifaddrs.h> +#endif +  #include <poll.h>  #include <sys/mman.h> -#ifdef HAVE_NETMAP +#if defined(HAVE_NETMAP)  #define NETMAP_WITH_LIBS  #include <net/netmap_user.h> +#elif defined(HAVE_BPF) +#define BPF_DEV_MAX               256 +#define BPF_BLEN                  sysconf(_SC_PAGESIZE) +#include <net/bpf.h>  #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); +  } | 
