summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordimitri staessens <dimitri.staessens@ugent.be>2017-08-17 14:51:47 +0000
committerSander Vrijders <sander.vrijders@ugent.be>2017-08-17 14:51:47 +0000
commitc7cb10810c447579cb20a8bc99049baeeb8e2065 (patch)
treedf6a08516b7215dddb024ab1e44f23121d616487 /src
parent44327027e32f5853995984a5bad9869b443898ca (diff)
parentdb218bbe19b66a382df5f665981b7b16f1901bc9 (diff)
downloadouroboros-c7cb10810c447579cb20a8bc99049baeeb8e2065.tar.gz
ouroboros-c7cb10810c447579cb20a8bc99049baeeb8e2065.zip
Merged in dstaesse/ouroboros/be-llc-bpf (pull request #556)
Be llc bpf
Diffstat (limited to 'src')
-rw-r--r--src/ipcpd/CMakeLists.txt4
-rw-r--r--src/ipcpd/shim-eth-llc/CMakeLists.txt63
-rw-r--r--src/ipcpd/shim-eth-llc/main.c330
-rw-r--r--src/irmd/ipcp.c53
-rw-r--r--src/irmd/main.c34
-rw-r--r--src/lib/random.c12
6 files changed, 308 insertions, 188 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(&eth_llc_data.fd_to_ef[i].r_addr, 0, MAC_SIZE);
}
+ ret = -1;
+
if (pthread_rwlock_init(&eth_llc_data.flows_lock, NULL))
- goto fqueue_destroy;
+ goto fail_flows_lock;
if (pthread_mutex_init(&eth_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(&eth_llc_data.mgmt_cond, &cattr))
- goto mgmt_lock_destroy;
+ goto fail_mgmt_cond;
+
+ pthread_condattr_destroy(&cattr);
list_head_init(&eth_llc_data.mgmt_frames);
return 0;
-
- mgmt_lock_destroy:
+ fail_mgmt_cond:
+ pthread_condattr_destroy(&cattr);
+ fail_condattr:
pthread_mutex_destroy(&eth_llc_data.mgmt_lock);
- flow_lock_destroy:
+ fail_mgmt_lock:
pthread_rwlock_destroy(&eth_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(&eth_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(&eth_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(&eth_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 *) &eth_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(&eth_llc_data.poll_in, 1, EVENT_WAIT_TIMEOUT) < 0)
+#if defined(HAVE_NETMAP)
+ if (poll(&eth_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(&eth_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(&eth_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, &eth_llc_ops) < 0) {
- ipcp_create_r(getpid(), -1);
- exit(EXIT_FAILURE);
- }
+ if (ipcp_init(argc, argv, THIS_TYPE, &eth_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);
+
}
diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c
index ade09625..f3f97811 100644
--- a/src/irmd/ipcp.c
+++ b/src/irmd/ipcp.c
@@ -130,13 +130,34 @@ pid_t ipcp_create(const char * name,
enum ipcp_type ipcp_type)
{
pid_t api = -1;
- size_t len = 0;
char * ipcp_dir = "/sbin/";
- char * full_name = NULL;
char * exec_name = NULL;
char irmd_api[10];
+ char full_name[256];
char * argv[5];
+ switch(ipcp_type) {
+ case IPCP_NORMAL:
+ exec_name = IPCP_NORMAL_EXEC;
+ break;
+ case IPCP_SHIM_UDP:
+ exec_name = IPCP_SHIM_UDP_EXEC;
+ break;
+ case IPCP_SHIM_ETH_LLC:
+ exec_name = IPCP_SHIM_ETH_LLC_EXEC;
+ break;
+ case IPCP_LOCAL:
+ exec_name = IPCP_LOCAL_EXEC;
+ break;
+ default:
+ return -1;
+ }
+
+ if (strlen(exec_name) == 0) {
+ log_err("IPCP type not installed.");
+ return -1;
+ }
+
sprintf(irmd_api, "%u", getpid());
api = fork();
@@ -148,33 +169,9 @@ pid_t ipcp_create(const char * name,
if (api != 0)
return api;
- if (ipcp_type == IPCP_NORMAL)
- exec_name = IPCP_NORMAL_EXEC;
- else if (ipcp_type == IPCP_SHIM_UDP)
- exec_name = IPCP_SHIM_UDP_EXEC;
- else if (ipcp_type == IPCP_SHIM_ETH_LLC)
- exec_name = IPCP_SHIM_ETH_LLC_EXEC;
- else if (ipcp_type == IPCP_LOCAL)
- exec_name = IPCP_LOCAL_EXEC;
- else
- exit(EXIT_FAILURE);
-
- len += strlen(INSTALL_PREFIX);
- len += strlen(ipcp_dir);
- len += strlen(exec_name);
- len += 1;
-
- full_name = malloc(len + 1);
- if (full_name == NULL) {
- log_err("Failed to malloc");
- exit(EXIT_FAILURE);
- }
-
strcpy(full_name, INSTALL_PREFIX);
strcat(full_name, ipcp_dir);
strcat(full_name, exec_name);
- full_name[len] = '\0';
-
/* log_file to be placed at the end */
argv[0] = full_name;
@@ -190,9 +187,7 @@ pid_t ipcp_create(const char * name,
execv(argv[0], &argv[0]);
log_dbg("%s", strerror(errno));
- log_err("Failed to load IPCP daemon");
- log_err("Make sure to run the installed version");
- free(full_name);
+ log_err("Failed to load IPCP daemon.");
exit(EXIT_FAILURE);
}
diff --git a/src/irmd/main.c b/src/irmd/main.c
index 61ce6a49..0c157fd4 100644
--- a/src/irmd/main.c
+++ b/src/irmd/main.c
@@ -275,6 +275,11 @@ static pid_t create_ipcp(char * name,
struct ipcp_entry * tmp = NULL;
struct list_head * p = NULL;
struct ipcp_entry * entry = NULL;
+ int ret = 0;
+ pthread_condattr_t cattr;
+ struct timespec dl;
+ struct timespec to = {SOCKET_TIMEOUT / 1000,
+ (SOCKET_TIMEOUT % 1000) * MILLION};
api = malloc(sizeof(*api));
if (api == NULL)
@@ -311,13 +316,20 @@ static pid_t create_ipcp(char * name,
pthread_rwlock_unlock(&irmd.reg_lock);
return -1;
}
+ pthread_condattr_init(&cattr);
+#ifndef __APPLE__
+ pthread_condattr_setclock(&cattr, PTHREAD_COND_CLOCK);
+#endif
+
+ pthread_cond_init(&tmp->init_cond, &cattr);
+
+ pthread_condattr_destroy(&cattr);
- pthread_cond_init(&tmp->init_cond, NULL);
pthread_mutex_init(&tmp->init_lock, NULL);
- tmp->dif_name = NULL;
- tmp->type = ipcp_type;
- tmp->init = false;
+ tmp->dif_name = NULL;
+ tmp->type = ipcp_type;
+ tmp->init = false;
tmp->dir_hash_algo = -1;
list_for_each(p, &irmd.ipcps) {
@@ -334,11 +346,21 @@ static pid_t create_ipcp(char * name,
pthread_mutex_lock(&tmp->init_lock);
- while (tmp->init == false)
- pthread_cond_wait(&tmp->init_cond, &tmp->init_lock);
+ clock_gettime(PTHREAD_COND_CLOCK, &dl);
+ ts_add(&dl, &to, &dl);
+ while (tmp->init == false && ret != -ETIMEDOUT)
+ ret = -pthread_cond_timedwait(&tmp->init_cond,
+ &tmp->init_lock,
+ &dl);
pthread_mutex_unlock(&tmp->init_lock);
+ if (ret == -ETIMEDOUT) {
+ log_err("Process %d failed to respond.", api->pid);
+ kill(api->pid, SIGKILL);
+ return -1;
+ }
+
log_info("Created IPCP %d.", api->pid);
return api->pid;
diff --git a/src/lib/random.c b/src/lib/random.c
index 5d6763ca..66aefaa3 100644
--- a/src/lib/random.c
+++ b/src/lib/random.c
@@ -47,18 +47,18 @@
int random_buffer(void * buf,
size_t len)
{
-#if defined(HAVE_SYS_RANDOM)
- return getrandom(buf, len, GRND_NONBLOCK); /* glibc 2.25 */
-#elif defined(HAVE_LIBGCRYPT)
- return gcry_randomize(buf, len, GCRY_STRONG_RANDOM);
+#if defined(__APPLE__)
+ return getentropy(buf, len);
#elif defined(__FreeBSD__)
arc4random_buf(buf, len);
return 0;
+#elif defined(HAVE_SYS_RANDOM)
+ return getrandom(buf, len, GRND_NONBLOCK); /* glibc 2.25 */
+#elif defined(HAVE_LIBGCRYPT)
+ return gcry_randomize(buf, len, GCRY_STRONG_RANDOM);
#elif defined(HAVE_OPENSSL)
if (len > 0 && len < INT_MAX)
return RAND_bytes((unsigned char *) buf, (int) len);
return -1;
-#elif defined(__APPLE__)
- return getentropy(buf, len);
#endif
}