Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/libtap/libtap.c b/libtap/libtap.c
index b4071eff..46c6dd27 100644
--- a/libtap/libtap.c
+++ b/libtap/libtap.c
@@ -1,848 +1,862 @@
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/if_tun.h>
#include <net/ethernet.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <limits.h>
+#include <stdio.h>
-#include "utils.h"
#include "libtap.h"
#include "libtap_private.h"
STATIC int tap_init = 0;
STATIC struct tap_config tap_cfg;
STATIC pthread_mutex_t tap_mutex = PTHREAD_MUTEX_INITIALIZER;
/* forward declarations */
-STATIC int tap_execute_shell(const char *command);
-static int tap_exec_updown(const knet_tap_t knet_tap, const char *action);
+STATIC int tap_execute_shell(const char *command, char **error_string);
+static int tap_exec_updown(const knet_tap_t knet_tap, const char *action, char **error_string);
static int tap_set_down(knet_tap_t knet_tap);
static int tap_read_pipe(int fd, char **file, size_t *length);
static int tap_check(const knet_tap_t knet_tap);
static void tap_close(knet_tap_t knet_tap);
static void tap_close_cfg(void);
static int tap_get_mtu(const knet_tap_t knet_tap);
static int tap_get_mac(const knet_tap_t knet_tap, char **ether_addr);
static int tap_set_down(knet_tap_t knet_tap);
static char *tap_get_v4_broadcast(const char *ip_addr, const char *prefix);
static int tap_set_ip(knet_tap_t knet_tap, const char *command,
- const char *ip_addr, const char *prefix);
+ const char *ip_addr, const char *prefix,
+ char **error_string);
static int tap_find_ip(knet_tap_t knet_tap,
const char *ip_addr, const char *prefix,
struct tap_ip **tap_ip, struct tap_ip **tap_ip_prev);
static int tap_read_pipe(int fd, char **file, size_t *length)
{
char buf[4096];
int n;
int done = 0;
*file = NULL;
*length = 0;
memset(buf, 0, sizeof(buf));
while (!done) {
n = read(fd, buf, sizeof(buf));
if (n < 0) {
if (errno == EINTR)
continue;
if (*file)
free(*file);
return n;
}
if (n == 0 && (!*length))
return 0;
if (n == 0)
done = 1;
if (*file)
*file = realloc(*file, (*length) + n + done);
else
*file = malloc(n + done);
if (!*file)
return -1;
memcpy((*file) + (*length), buf, n);
*length += (done + n);
}
/* Null terminator */
(*file)[(*length) - 1] = 0;
return 0;
}
-STATIC int tap_execute_shell(const char *command)
+STATIC int tap_execute_shell(const char *command, char **error_string)
{
pid_t pid;
int status, err = 0;
int fd[2];
- char *data = NULL;
size_t size = 0;
- if (command == NULL) {
+ if ((command == NULL) || (!error_string)) {
errno = EINVAL;
return -1;
}
+ *error_string = NULL;
+
err = pipe(fd);
if (err)
goto out_clean;
pid = fork();
if (pid < 0) {
err = pid;
goto out_clean;
}
if (pid) { /* parent */
close(fd[1]);
- err = tap_read_pipe(fd[0], &data, &size);
+ err = tap_read_pipe(fd[0], error_string, &size);
if (err)
goto out_clean;
waitpid(pid, &status, 0);
if (!WIFEXITED(status)) {
- log_error("shell: child did not terminate normally");
err = -1;
goto out_clean;
}
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
- log_error("shell: child returned %d", WEXITSTATUS(status));
- err = -1;
+ err = WEXITSTATUS(status);
goto out_clean;
}
} else { /* child */
close(0);
close(1);
close(2);
close(fd[0]);
- if(dup2(fd[1], 1) < 0)
- log_error("Unable to redirect stdout");
- if(dup2(fd[1], 2) < 0)
- log_error("Unable to redirect stderr");
+ dup2(fd[1], 1);
+ dup2(fd[1], 2);
close(fd[1]);
execlp("/bin/sh", "/bin/sh", "-c", command, NULL);
exit(EXIT_FAILURE);
}
out_clean:
close(fd[0]);
close(fd[1]);
- if ((size) && (err)) {
- log_error("%s", data);
- free(data);
- }
-
return err;
}
-static int tap_exec_updown(const knet_tap_t knet_tap, const char *action)
+static int tap_exec_updown(const knet_tap_t knet_tap, const char *action, char **error_string)
{
char command[PATH_MAX];
if (!knet_tap->hasupdown)
return 0;
memset(command, 0, PATH_MAX);
snprintf(command, PATH_MAX, "%s%s/%s", knet_tap->updownpath, action, knet_tap->ifname);
- return tap_execute_shell(command);
+ return tap_execute_shell(command, error_string);
}
static int tap_check(const knet_tap_t knet_tap)
{
knet_tap_t temp = tap_cfg.tap_head;
if (!knet_tap)
return 0;
while (temp != NULL) {
if (knet_tap == temp)
return 1;
temp = temp->next;
}
return 0;
}
static void tap_close(knet_tap_t knet_tap)
{
if (!knet_tap)
return;
if (knet_tap->knet_tap_fd)
close(knet_tap->knet_tap_fd);
free(knet_tap);
return;
}
static void tap_close_cfg(void)
{
if (tap_cfg.tap_head == NULL) {
close(tap_cfg.tap_sockfd);
tap_init = 0;
}
}
static int tap_get_mtu(const knet_tap_t knet_tap)
{
int err;
err = ioctl(tap_cfg.tap_sockfd, SIOCGIFMTU, &knet_tap->ifr);
if (err)
goto out_clean;
err = knet_tap->ifr.ifr_mtu;
out_clean:
return err;
}
static int tap_get_mac(const knet_tap_t knet_tap, char **ether_addr)
{
int err;
char mac[MAX_MAC_CHAR];
err = ioctl(tap_cfg.tap_sockfd, SIOCGIFHWADDR, &knet_tap->ifr);
if (err)
goto out_clean;
ether_ntoa_r((struct ether_addr *)knet_tap->ifr.ifr_hwaddr.sa_data, mac);
*ether_addr = strdup(mac);
if (!*ether_addr)
err = -1;
out_clean:
return err;
}
knet_tap_t knet_tap_find(char *dev, size_t dev_size)
{
knet_tap_t knet_tap;
if (dev == NULL) {
errno = EINVAL;
return NULL;
}
if (dev_size < IFNAMSIZ) {
errno = EINVAL;
return NULL;
}
if (strlen(dev) > IFNAMSIZ) {
errno = E2BIG;
return NULL;
}
pthread_mutex_lock(&tap_mutex);
knet_tap = tap_cfg.tap_head;
while (knet_tap != NULL) {
if (!strcmp(dev, knet_tap->ifname))
break;
knet_tap = knet_tap->next;
}
pthread_mutex_unlock(&tap_mutex);
return knet_tap;
}
knet_tap_t knet_tap_open(char *dev, size_t dev_size, const char *updownpath)
{
knet_tap_t knet_tap;
char *temp_mac = NULL;
if (dev == NULL) {
errno = EINVAL;
return NULL;
}
if (dev_size < IFNAMSIZ) {
errno = EINVAL;
return NULL;
}
if (strlen(dev) > IFNAMSIZ) {
errno = E2BIG;
return NULL;
}
if (updownpath) {
/* only absolute paths */
if (updownpath[0] != '/') {
errno = EINVAL;
return NULL;
}
/* 14: 2 for /, 1 for \0 + 11 (post-down.d) */
if (strlen(updownpath) >= (PATH_MAX - (strlen(dev) + 14))) {
errno = E2BIG;
return NULL;
}
}
pthread_mutex_lock(&tap_mutex);
knet_tap = malloc(sizeof(struct tap_iface));
if (!knet_tap)
return NULL;
memset(knet_tap, 0, sizeof(struct tap_iface));
if ((knet_tap->knet_tap_fd = open("/dev/net/tun", O_RDWR)) < 0)
goto out_error;
strncpy(knet_tap->ifname, dev, IFNAMSIZ);
knet_tap->ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
if (ioctl(knet_tap->knet_tap_fd, TUNSETIFF, &knet_tap->ifr) < 0)
goto out_error;
if ((strlen(dev) > 0) && (strcmp(dev, knet_tap->ifname) != 0)) {
errno = EBUSY;
goto out_error;
}
strcpy(dev, knet_tap->ifname);
if (!tap_init) {
tap_cfg.tap_head = NULL;
tap_cfg.tap_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (tap_cfg.tap_sockfd < 0)
goto out_error;
tap_init = 1;
}
if (ioctl(tap_cfg.tap_sockfd, SIOGIFINDEX, &knet_tap->ifr) < 0)
goto out_error;
knet_tap->default_mtu = tap_get_mtu(knet_tap);
if (knet_tap->default_mtu < 0)
goto out_error;
if (tap_get_mac(knet_tap, &temp_mac) < 0)
goto out_error;
strncpy(knet_tap->default_mac, temp_mac, 18);
free(temp_mac);
if (updownpath) {
int len = strlen(updownpath);
strcpy(knet_tap->updownpath, updownpath);
if (knet_tap->updownpath[len-1] != '/') {
knet_tap->updownpath[len] = '/';
}
knet_tap->hasupdown = 1;
}
knet_tap->next = tap_cfg.tap_head;
tap_cfg.tap_head = knet_tap;
pthread_mutex_unlock(&tap_mutex);
return knet_tap;
out_error:
tap_close(knet_tap);
tap_close_cfg();
pthread_mutex_unlock(&tap_mutex);
return NULL;
}
int knet_tap_close(knet_tap_t knet_tap)
{
int err = 0;
knet_tap_t temp = tap_cfg.tap_head;
knet_tap_t prev = tap_cfg.tap_head;
struct tap_ip *tap_ip, *tap_ip_next;
+ char *error_string = NULL;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
while ((temp) && (temp != knet_tap)) {
prev = temp;
temp = temp->next;
}
if (knet_tap == prev) {
tap_cfg.tap_head = knet_tap->next;
} else {
prev->next = knet_tap->next;
}
tap_set_down(knet_tap);
tap_ip = knet_tap->tap_ip;
while (tap_ip) {
tap_ip_next = tap_ip->next;
- tap_set_ip(knet_tap, "del", tap_ip->ip_addr, tap_ip->prefix);
+ tap_set_ip(knet_tap, "del", tap_ip->ip_addr, tap_ip->prefix, &error_string);
+ if (error_string)
+ free(error_string);
free(tap_ip);
tap_ip = tap_ip_next;
}
tap_close(knet_tap);
tap_close_cfg();
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_get_mtu(const knet_tap_t knet_tap)
{
int err;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
err = tap_get_mtu(knet_tap);
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_set_mtu(knet_tap_t knet_tap, const int mtu)
{
int err, oldmtu;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
oldmtu = knet_tap->ifr.ifr_mtu;
knet_tap->ifr.ifr_mtu = mtu;
err = ioctl(tap_cfg.tap_sockfd, SIOCSIFMTU, &knet_tap->ifr);
if (err)
knet_tap->ifr.ifr_mtu = oldmtu;
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_reset_mtu(knet_tap_t knet_tap)
{
return knet_tap_set_mtu(knet_tap, knet_tap->default_mtu);
}
int knet_tap_get_mac(const knet_tap_t knet_tap, char **ether_addr)
{
int err;
pthread_mutex_lock(&tap_mutex);
if ((!tap_check(knet_tap)) || (!ether_addr)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
err = tap_get_mac(knet_tap, ether_addr);
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_set_mac(knet_tap_t knet_tap, const char *ether_addr)
{
struct ether_addr oldmac;
int err;
pthread_mutex_lock(&tap_mutex);
if ((!tap_check(knet_tap)) || (!ether_addr)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
memcpy(&oldmac, knet_tap->ifr.ifr_hwaddr.sa_data, ETH_ALEN);
memcpy(knet_tap->ifr.ifr_hwaddr.sa_data, ether_aton(ether_addr), ETH_ALEN);
err = ioctl(tap_cfg.tap_sockfd, SIOCSIFHWADDR, &knet_tap->ifr);
if (err)
memcpy(knet_tap->ifr.ifr_hwaddr.sa_data, &oldmac, ETH_ALEN);
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_reset_mac(knet_tap_t knet_tap)
{
return knet_tap_set_mac(knet_tap, knet_tap->default_mac);
}
int knet_tap_set_up(knet_tap_t knet_tap)
{
int err = 0;
short int oldflags;
+ char *error_string = NULL;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
if (knet_tap->up)
goto out_clean;
- tap_exec_updown(knet_tap, "pre-up.d");
+ tap_exec_updown(knet_tap, "pre-up.d", &error_string);
+ if (error_string)
+ free(error_string);
oldflags = knet_tap->ifr.ifr_flags;
knet_tap->ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
err=ioctl(tap_cfg.tap_sockfd, SIOCSIFFLAGS, &knet_tap->ifr);
if (err)
knet_tap->ifr.ifr_flags = oldflags;
- tap_exec_updown(knet_tap, "up.d");
+ tap_exec_updown(knet_tap, "up.d", &error_string);
+ if (error_string)
+ free(error_string);
knet_tap->up = 1;
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
static int tap_set_down(knet_tap_t knet_tap)
{
int err = 0;
short int oldflags;
+ char *error_string = NULL;
if (!knet_tap->up)
goto out_clean;
- tap_exec_updown(knet_tap, "down.d");
+ tap_exec_updown(knet_tap, "down.d", &error_string);
+ if (error_string)
+ free(error_string);
oldflags = knet_tap->ifr.ifr_flags;
knet_tap->ifr.ifr_flags &= ~IFF_UP;
err=ioctl(tap_cfg.tap_sockfd, SIOCSIFFLAGS, &knet_tap->ifr);
if (err) {
knet_tap->ifr.ifr_flags = oldflags;
goto out_clean;
}
- tap_exec_updown(knet_tap, "post-down.d");
+ tap_exec_updown(knet_tap, "post-down.d", &error_string);
+ if (error_string)
+ free(error_string);
knet_tap->up = 0;
out_clean:
return err;
}
int knet_tap_set_down(knet_tap_t knet_tap)
{
int err = 0;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
err=tap_set_down(knet_tap);
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
static char *tap_get_v4_broadcast(const char *ip_addr, const char *prefix)
{
int prefix_len;
struct in_addr mask;
struct in_addr broadcast;
struct in_addr address;
prefix_len = atoi(prefix);
if ((prefix_len > 32) || (prefix_len < 0))
return NULL;
if (inet_pton(AF_INET, ip_addr, &address) <= 0)
return NULL;
mask.s_addr = htonl(~((1 << (32 - prefix_len)) - 1));
memset(&broadcast, 0, sizeof(broadcast));
broadcast.s_addr = (address.s_addr & mask.s_addr) | ~mask.s_addr;
return strdup(inet_ntoa(broadcast));
}
static int tap_set_ip(knet_tap_t knet_tap, const char *command,
- const char *ip_addr, const char *prefix)
+ const char *ip_addr, const char *prefix,
+ char **error_string)
{
char *broadcast = NULL;
char cmdline[4096];
if (!strchr(ip_addr, ':')) {
broadcast = tap_get_v4_broadcast(ip_addr, prefix);
if (!broadcast) {
errno = EINVAL;
return -1;
}
}
memset(cmdline, 0, sizeof(cmdline));
if (broadcast) {
snprintf(cmdline, sizeof(cmdline)-1,
"ip addr %s %s/%s dev %s broadcast %s",
command, ip_addr, prefix,
knet_tap->ifname, broadcast);
free(broadcast);
} else {
snprintf(cmdline, sizeof(cmdline)-1,
"ip addr %s %s/%s dev %s",
command, ip_addr, prefix,
knet_tap->ifname);
}
- return tap_execute_shell(cmdline);
+ return tap_execute_shell(cmdline, error_string);
}
static int tap_find_ip(knet_tap_t knet_tap,
const char *ip_addr, const char *prefix,
struct tap_ip **tap_ip, struct tap_ip **tap_ip_prev)
{
struct tap_ip *local_tap_ip, *local_tap_ip_prev;
int found = 0;
local_tap_ip = local_tap_ip_prev = knet_tap->tap_ip;
while(local_tap_ip) {
if ((!strcmp(local_tap_ip->ip_addr, ip_addr)) && (!strcmp(local_tap_ip->prefix, prefix))) {
found = 1;
break;
}
local_tap_ip_prev = local_tap_ip;
local_tap_ip = local_tap_ip->next;
}
if (found) {
*tap_ip = local_tap_ip;
*tap_ip_prev = local_tap_ip_prev;
}
return found;
}
int knet_tap_add_ip(knet_tap_t knet_tap, const char *ip_addr, const char *prefix)
{
int err = 0, found;
struct tap_ip *tap_ip = NULL, *tap_ip_prev = NULL;
+ char *error_string = NULL;
pthread_mutex_lock(&tap_mutex);
if ((!tap_check(knet_tap)) || (!ip_addr) || (!prefix)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
found = tap_find_ip(knet_tap, ip_addr, prefix, &tap_ip, &tap_ip_prev);
if (found)
goto out_clean;
tap_ip = malloc(sizeof(struct tap_ip));
if (!tap_ip) {
err = -1 ;
goto out_clean;
}
memset(tap_ip, 0, sizeof(struct tap_ip));
strncpy(tap_ip->ip_addr, ip_addr, MAX_IP_CHAR);
strncpy(tap_ip->prefix, prefix, MAX_PREFIX_CHAR);
- err = tap_set_ip(knet_tap, "add", ip_addr, prefix);
+ err = tap_set_ip(knet_tap, "add", ip_addr, prefix, &error_string);
+ if (error_string)
+ free(error_string);
+
if (err) {
free(tap_ip);
goto out_clean;
}
tap_ip->next = knet_tap->tap_ip;
knet_tap->tap_ip = tap_ip;
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_del_ip(knet_tap_t knet_tap, const char *ip_addr, const char *prefix)
{
int err = 0, found;
struct tap_ip *tap_ip = NULL, *tap_ip_prev = NULL;
+ char *error_string = NULL;
pthread_mutex_lock(&tap_mutex);
if ((!tap_check(knet_tap)) || (!ip_addr) || (!prefix)) {
errno = EINVAL;
err = -1;
goto out_clean;
}
found = tap_find_ip(knet_tap, ip_addr, prefix, &tap_ip, &tap_ip_prev);
if (!found)
goto out_clean;
- err = tap_set_ip(knet_tap, "del", ip_addr, prefix);
+ err = tap_set_ip(knet_tap, "del", ip_addr, prefix, &error_string);
+ if (error_string)
+ free(error_string);
if (!err) {
if (tap_ip == tap_ip_prev) {
knet_tap->tap_ip = tap_ip->next;
} else {
tap_ip_prev->next = tap_ip->next;
}
free(tap_ip);
}
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
int knet_tap_get_fd(const knet_tap_t knet_tap)
{
int fd;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
fd = -1;
goto out_clean;
}
fd = knet_tap->knet_tap_fd;
out_clean:
pthread_mutex_unlock(&tap_mutex);
return fd;
}
const char *knet_tap_get_name(const knet_tap_t knet_tap)
{
char *name = NULL;
pthread_mutex_lock(&tap_mutex);
if (!tap_check(knet_tap)) {
errno = EINVAL;
goto out_clean;
}
name = knet_tap->ifname;
out_clean:
pthread_mutex_unlock(&tap_mutex);
return name;
}
int knet_tap_get_ips(const knet_tap_t knet_tap, char **ip_addr_list, int *entries)
{
int err = 0;
int found = 0;
char *ip_list = NULL;
int size = 0, offset = 0, len;
struct tap_ip *tap_ip = knet_tap->tap_ip;
pthread_mutex_lock(&tap_mutex);
while (tap_ip) {
found++;
tap_ip = tap_ip->next;
}
size = found * (MAX_IP_CHAR + MAX_PREFIX_CHAR + 2);
ip_list = malloc(size);
if (!ip_list) {
err = -1;
goto out_clean;
}
memset(ip_list, 0, size);
tap_ip = knet_tap->tap_ip;
while (tap_ip) {
len = strlen(tap_ip->ip_addr);
memcpy(ip_list + offset, tap_ip->ip_addr, len);
offset = offset + len + 1;
len = strlen(tap_ip->prefix);
memcpy(ip_list + offset, tap_ip->prefix, len);
offset = offset + len + 1;
tap_ip = tap_ip->next;
}
*ip_addr_list = ip_list;
*entries = found;
out_clean:
pthread_mutex_unlock(&tap_mutex);
return err;
}
diff --git a/libtap/libtap_private.h b/libtap/libtap_private.h
index 762d8965..bd780fb6 100644
--- a/libtap/libtap_private.h
+++ b/libtap/libtap_private.h
@@ -1,35 +1,41 @@
#ifndef __LIBTAP_PRIVATE_H__
#define __LIBTAP_PRIVATE_H__
#include <net/if.h>
#include <limits.h>
+#ifndef TEST
+#define STATIC static
+#else
+#define STATIC
+#endif
+
#define MAX_IP_CHAR 128
#define MAX_PREFIX_CHAR 4
#define MAX_MAC_CHAR 18
struct tap_ip {
char ip_addr[MAX_IP_CHAR];
char prefix[MAX_PREFIX_CHAR];
struct tap_ip *next;
};
struct tap_iface {
struct ifreq ifr;
int knet_tap_fd;
char default_mac[MAX_MAC_CHAR];
int default_mtu;
char updownpath[PATH_MAX];
int hasupdown;
int up;
struct tap_ip *tap_ip;
struct tap_iface *next;
};
#define ifname ifr.ifr_name
struct tap_config {
struct tap_iface *tap_head;
int tap_sockfd;
};
#endif
diff --git a/tests/tap_test.c b/tests/tap_test.c
index 2233f512..3de67ebc 100644
--- a/tests/tap_test.c
+++ b/tests/tap_test.c
@@ -1,793 +1,869 @@
#include "config.h"
#include <string.h>
#include <errno.h>
#include <net/if.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netinet/ether.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include "libtap.h"
#include "libtap_private.h"
#include "utils.h"
extern struct tap_config tap_cfg;
-extern int tap_execute_shell(const char *command);
+extern int tap_execute_shell(const char *command, char **error_string);
static int is_if_in_system(char *name)
{
struct ifaddrs *ifap = NULL;
struct ifaddrs *ifa;
int found = 0;
if (getifaddrs(&ifap) < 0) {
log_error("Unable to get interface list.");
return -1;
}
ifa = ifap;
while (ifa) {
if (!strncmp(name, ifa->ifa_name, IFNAMSIZ)) {
found = 1;
break;
}
ifa=ifa->ifa_next;
}
freeifaddrs(ifap);
return found;
}
static int test_iface(char *name, size_t size, const char *updownpath)
{
knet_tap_t knet_tap;
knet_tap=knet_tap_open(name, size, updownpath);
if (!knet_tap) {
if (tap_cfg.tap_sockfd < 0)
log_error("Unable to open knet_socket");
log_error("Unable to open knet.");
return -1;
}
log_info("Created interface: %s", name);
if (is_if_in_system(name) > 0) {
log_info("Found interface %s on the system", name);
} else {
log_info("Unable to find interface %s on the system", name);
}
if (!knet_tap_find(name, size)) {
log_info("Unable to find interface %s in tap db", name);
} else {
log_info("Found interface %s in tap db", name);
}
knet_tap_close(knet_tap);
if (is_if_in_system(name) == 0)
log_info("Successfully removed interface %s from the system", name);
return 0;
}
static int check_knet_tap_open_close(void)
{
char device_name[2*IFNAMSIZ];
char fakepath[PATH_MAX];
size_t size = IFNAMSIZ;
memset(device_name, 0, sizeof(device_name));
log_info("Creating random tap interface:");
if (test_iface(device_name, size, NULL) < 0) {
log_error("Unable to create random interface");
return -1;
}
log_info("Creating kronostest tap interface:");
strncpy(device_name, "kronostest", IFNAMSIZ);
if (test_iface(device_name, size, NULL) < 0) {
log_error("Unable to create kronosnet interface");
return -1;
}
log_info("Testing ERROR conditions");
log_info("Testing dev == NULL");
errno=0;
if ((test_iface(NULL, size, NULL) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_open sanity checks");
return -1;
}
log_info("Testing size < IFNAMSIZ");
errno=0;
if ((test_iface(device_name, 1, NULL) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_open sanity checks");
return -1;
}
log_info("Testing device_name size > IFNAMSIZ");
errno=0;
strcpy(device_name, "abcdefghilmnopqrstuvwz");
if ((test_iface(device_name, IFNAMSIZ, NULL) >= 0) || (errno != E2BIG)) {
log_error("Something is wrong in knet_tap_open sanity checks");
return -1;
}
log_info("Testing updown path != abs");
errno=0;
strcpy(device_name, "kronostest");
if ((test_iface(device_name, IFNAMSIZ, "foo") >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_open sanity checks");
return -1;
}
memset(fakepath, '/', PATH_MAX - 2);
fakepath[PATH_MAX-1] = 0;
log_info("Testing updown path > PATH_MAX");
errno=0;
strcpy(device_name, "kronostest");
if ((test_iface(device_name, IFNAMSIZ, fakepath) >= 0) || (errno != E2BIG)) {
log_error("Something is wrong in knet_tap_open sanity checks");
return -1;
}
return 0;
}
static int check_knet_multi_eth(void)
{
char device_name1[IFNAMSIZ];
char device_name2[IFNAMSIZ];
size_t size = IFNAMSIZ;
int err=0;
knet_tap_t knet_tap1 = NULL;
knet_tap_t knet_tap2 = NULL;
log_info("Testing multiple knet interface instances");
memset(device_name1, 0, size);
memset(device_name2, 0, size);
strncpy(device_name1, "kronostest1", size);
strncpy(device_name2, "kronostest2", size);
knet_tap1 = knet_tap_open(device_name1, size, NULL);
if (!knet_tap1) {
log_error("Unable to init %s.", device_name1);
err = -1;
goto out_clean;
}
if (is_if_in_system(device_name1) > 0) {
log_info("Found interface %s on the system", device_name1);
} else {
log_info("Unable to find interface %s on the system", device_name1);
}
knet_tap2 = knet_tap_open(device_name2, size, NULL);
if (!knet_tap2) {
log_error("Unable to init %s.", device_name2);
err = -1;
goto out_clean;
}
if (is_if_in_system(device_name2) > 0) {
log_info("Found interface %s on the system", device_name2);
} else {
log_info("Unable to find interface %s on the system", device_name2);
}
if (knet_tap1)
knet_tap_close(knet_tap1);
if (knet_tap2)
knet_tap_close(knet_tap2);
log_info("Testing error conditions");
log_info("Open same device twice");
knet_tap1 = knet_tap_open(device_name1, size, NULL);
if (!knet_tap1) {
log_error("Unable to init %s.", device_name1);
err = -1;
goto out_clean;
}
if (is_if_in_system(device_name1) > 0) {
log_info("Found interface %s on the system", device_name1);
} else {
log_info("Unable to find interface %s on the system", device_name1);
}
knet_tap2 = knet_tap_open(device_name1, size, NULL);
if (knet_tap2) {
log_error("We were able to init 2 interfaces with the same name!");
err = -1;
goto out_clean;
}
out_clean:
if (knet_tap1)
knet_tap_close(knet_tap1);
if (knet_tap2)
knet_tap_close(knet_tap2);
return err;
}
static int check_knet_mtu(void)
{
char device_name[IFNAMSIZ];
size_t size = IFNAMSIZ;
int err=0;
knet_tap_t knet_tap;
int current_mtu = 0;
int expected_mtu = 1500;
log_info("Testing get/set MTU");
memset(device_name, 0, size);
strncpy(device_name, "kronostest", size);
knet_tap = knet_tap_open(device_name, size, NULL);
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Comparing default MTU");
current_mtu = knet_tap_get_mtu(knet_tap);
if (current_mtu < 0) {
log_error("Unable to get MTU");
err = -1;
goto out_clean;
}
if (current_mtu != expected_mtu) {
log_error("current mtu [%d] does not match expected default [%d]", current_mtu, expected_mtu);
err = -1;
goto out_clean;
}
log_info("Setting MTU to 9000");
expected_mtu = 9000;
if (knet_tap_set_mtu(knet_tap, expected_mtu) < 0) {
log_error("Unable to set MTU to %d.", expected_mtu);
err = -1;
goto out_clean;
}
current_mtu = knet_tap_get_mtu(knet_tap);
if (current_mtu < 0) {
log_error("Unable to get MTU");
err = -1;
goto out_clean;
}
if (current_mtu != expected_mtu) {
log_error("current mtu [%d] does not match expected value [%d]", current_mtu, expected_mtu);
err = -1;
goto out_clean;
}
log_info("Testing ERROR conditions");
log_info("Passing empty struct to get_mtu");
if (knet_tap_get_mtu(NULL) > 0) {
log_error("Something is wrong in knet_tap_get_mtu sanity checks");
err = -1;
goto out_clean;
}
log_info("Passing empty struct to set_mtu");
if (knet_tap_set_mtu(NULL, 1500) == 0) {
log_error("Something is wrong in knet_tap_set_mtu sanity checks");
err = -1;
goto out_clean;
}
out_clean:
knet_tap_close(knet_tap);
return err;
}
static int check_knet_mac(void)
{
char device_name[IFNAMSIZ];
size_t size = IFNAMSIZ;
int err=0;
knet_tap_t knet_tap;
char *current_mac = NULL, *temp_mac = NULL, *err_mac = NULL;
struct ether_addr *cur_mac, *tmp_mac;
log_info("Testing get/set MAC");
memset(device_name, 0, size);
strncpy(device_name, "kronostest", size);
knet_tap = knet_tap_open(device_name, size, NULL);
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Get current MAC");
if (knet_tap_get_mac(knet_tap, &current_mac) < 0) {
log_error("Unable to get current MAC address.");
err = -1;
goto out_clean;
}
log_info("Current MAC: %s", current_mac);
log_info("Setting MAC: 00:01:01:01:01:01");
if (knet_tap_set_mac(knet_tap, "00:01:01:01:01:01") < 0) {
log_error("Unable to set current MAC address.");
err = -1;
goto out_clean;
}
if (knet_tap_get_mac(knet_tap, &temp_mac) < 0) {
log_error("Unable to get current MAC address.");
err = -1;
goto out_clean;
}
log_info("Current MAC: %s", temp_mac);
cur_mac = ether_aton(current_mac);
tmp_mac = ether_aton(temp_mac);
log_info("Comparing MAC addresses");
if (memcmp(cur_mac, tmp_mac, sizeof(struct ether_addr))) {
log_error("Mac addresses are not the same?!");
err = -1;
goto out_clean;
}
log_info("Testing ERROR conditions");
log_info("Pass NULL to get_mac (pass1)");
errno = 0;
if ((knet_tap_get_mac(NULL, &err_mac) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_get_mac sanity checks");
err = -1;
goto out_clean;
}
log_info("Pass NULL to get_mac (pass2)");
errno = 0;
if ((knet_tap_get_mac(knet_tap, NULL) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_get_mac sanity checks");
err = -1;
goto out_clean;
}
log_info("Pass NULL to set_mac (pass1)");
errno = 0;
if ((knet_tap_set_mac(knet_tap, NULL) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_set_mac sanity checks");
err = -1;
goto out_clean;
}
log_info("Pass NULL to set_mac (pass2)");
errno = 0;
if ((knet_tap_set_mac(NULL, err_mac) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_set_mac sanity checks");
err = -1;
goto out_clean;
}
out_clean:
if (err_mac) {
log_error("Something managed to set err_mac!");
err = -1;
free(err_mac);
}
if (current_mac)
free(current_mac);
if (temp_mac)
free(temp_mac);
knet_tap_close(knet_tap);
return err;
}
static int check_tap_execute_shell(void)
{
int err = 0;
char command[4096];
+ char *error_string = NULL;
memset(command, 0, sizeof(command));
log_info("Testing tap_execute_shell");
log_info("command /bin/true");
- if (tap_execute_shell("/bin/true") < 0) {
+ err = tap_execute_shell("/bin/true", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (err < 0) {
log_error("Unable to execute /bin/true ?!?!");
- err = -1;
goto out_clean;
}
log_info("Testing ERROR conditions");
log_info("command /bin/false");
- if (!tap_execute_shell("/bin/false")) {
+ err = tap_execute_shell("/bin/false", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Can we really execute /bin/false successfully?!?!");
err = -1;
goto out_clean;
}
log_info("command that outputs to stdout (enforcing redirect)");
- if (!tap_execute_shell("/bin/grep -h 2>&1")) {
+
+ err = tap_execute_shell("/bin/grep -h 2>&1", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Can we really execute /bin/grep -h successfully?!?");
err = -1;
goto out_clean;
}
log_info("command that outputs to stderr");
- if (!tap_execute_shell("/bin/grep -h")) {
+ err = tap_execute_shell("/bin/grep -h", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Can we really execute /bin/grep -h successfully?!?");
err = -1;
goto out_clean;
}
log_info("empty command");
- if (!tap_execute_shell(NULL)) {
+ err = tap_execute_shell(NULL, &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Can we really execute (nil) successfully?!?!");
err = -1;
goto out_clean;
}
+ log_info("empty error");
+ err = tap_execute_shell("/bin/true", NULL);
+ if (!err) {
+ log_error("Check EINVAL filter for no error_string!");
+ err = -1;
+ goto out_clean;
+ }
+
+ err = 0;
+
out_clean:
return err;
}
static int check_knet_up_down(void)
{
char device_name[IFNAMSIZ];
size_t size = IFNAMSIZ;
int err=0;
knet_tap_t knet_tap;
+ char *error_string = NULL;
log_info("Testing interface up/down");
memset(device_name, 0, size);
strncpy(device_name, "kronostest", size);
knet_tap = knet_tap_open(device_name, size, NULL);
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Put the interface up");
if (knet_tap_set_up(knet_tap) < 0) {
log_error("Unable to set interface up");
err = -1;
goto out_clean;
}
- if (tap_execute_shell("ip addr show dev kronostest | grep -q UP") < 0) {
+
+ err = tap_execute_shell("ip addr show dev kronostest | grep -q UP", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (err < 0) {
log_error("Unable to verify inteface UP");
err = -1;
goto out_clean;
}
log_info("Put the interface down");
if (knet_tap_set_down(knet_tap) < 0) {
log_error("Unable to put the interface down");
err = -1;
goto out_clean;
}
- log_info("A shell error here is NORMAL");
-
- if (!tap_execute_shell("ifconfig kronostest | grep -q UP")) {
+ err = tap_execute_shell("ifconfig kronostest | grep -q UP", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Unable to verify inteface DOWN");
err = -1;
goto out_clean;
}
knet_tap_close(knet_tap);
log_info("Testing interface pre-up/up/down/post-down (exec errors)");
knet_tap = knet_tap_open(device_name, size, ABSBUILDDIR "/tap_updown_bad");
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Put the interface up");
if (knet_tap_set_up(knet_tap) < 0) {
log_error("Unable to set interface up");
err = -1;
goto out_clean;
}
log_info("Put the interface down");
if (knet_tap_set_down(knet_tap) < 0) {
log_error("Unable to put the interface down");
err = -1;
goto out_clean;
}
knet_tap_close(knet_tap);
log_info("Testing interface pre-up/up/down/post-down");
knet_tap = knet_tap_open(device_name, size, ABSBUILDDIR "/tap_updown_good");
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Put the interface up");
if (knet_tap_set_up(knet_tap) < 0) {
log_error("Unable to set interface up");
err = -1;
goto out_clean;
}
log_info("Put the interface down");
if (knet_tap_set_down(knet_tap) < 0) {
log_error("Unable to put the interface down");
err = -1;
goto out_clean;
}
knet_tap_close(knet_tap);
log_info("Test ERROR conditions");
log_info("Pass NULL to set_up");
errno = 0;
if ((knet_tap_set_up(NULL) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_set_up sanity checks");
err = -1;
goto out_clean;
}
log_info("Pass NULL to set_down");
errno = 0;
if ((knet_tap_set_down(NULL) >= 0) || (errno != EINVAL)) {
log_error("Something is wrong in knet_tap_set_down sanity checks");
err = -1;
goto out_clean;
}
out_clean:
knet_tap_close(knet_tap);
return err;
}
static int check_knet_close_leak(void)
{
char device_name[IFNAMSIZ];
size_t size = IFNAMSIZ;
int err=0;
knet_tap_t knet_tap;
log_info("Testing close leak (needs valgrind)");
memset(device_name, 0, size);
strncpy(device_name, "kronostest", size);
knet_tap = knet_tap_open(device_name, size, NULL);
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Adding ip: 192.168.168.168/24");
if (knet_tap_add_ip(knet_tap, "192.168.168.168", "24") < 0) {
log_error("Unable to assign IP address");
err=-1;
goto out_clean;
}
log_info("Adding ip: 192.168.169.169/24");
if (knet_tap_add_ip(knet_tap, "192.168.169.169", "24") < 0) {
log_error("Unable to assign IP address");
err=-1;
goto out_clean;
}
out_clean:
knet_tap_close(knet_tap);
return err;
}
static int check_knet_set_del_ip(void)
{
char device_name[IFNAMSIZ];
size_t size = IFNAMSIZ;
int err=0;
knet_tap_t knet_tap;
char *ip_list = NULL;
int ip_list_entries = 0, i, offset = 0;
+ char *error_string = NULL;
log_info("Testing interface add/remove ip");
memset(device_name, 0, size);
strncpy(device_name, "kronostest", size);
knet_tap = knet_tap_open(device_name, size, NULL);
if (!knet_tap) {
log_error("Unable to init %s.", device_name);
return -1;
}
log_info("Adding ip: 192.168.168.168/24");
if (knet_tap_add_ip(knet_tap, "192.168.168.168", "24") < 0) {
log_error("Unable to assign IP address");
err=-1;
goto out_clean;
}
log_info("Adding ip: 192.168.169.169/24");
if (knet_tap_add_ip(knet_tap, "192.168.169.169", "24") < 0) {
log_error("Unable to assign IP address");
err=-1;
goto out_clean;
}
log_info("Adding duplicate ip: 192.168.168.168/24");
if (knet_tap_add_ip(knet_tap, "192.168.168.168", "24") < 0) {
log_error("Unable to find IP address in libtap db");
err=-1;
goto out_clean;
}
log_info("Checking ip: 192.168.168.168/24");
- if (tap_execute_shell("ip addr show dev kronostest | grep -q 192.168.168.168/24")) {
+ err = tap_execute_shell("ip addr show dev kronostest | grep -q 192.168.168.168/24", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (err) {
log_error("Unable to verify IP address");
err=-1;
goto out_clean;
}
log_info("Get ip list from libtap:");
if (knet_tap_get_ips(knet_tap, &ip_list, &ip_list_entries) < 0) {
log_error("Not enough mem?");
err=-1;
goto out_clean;
}
if (ip_list_entries != 2) {
log_error("Didn't get enough ip back from libtap?");
err=-1;
goto out_clean;
}
for (i = 1; i <= ip_list_entries; i++) {
log_info("Found IP %s %s in libtap db", ip_list + offset, ip_list + offset + strlen(ip_list + offset) + 1);
offset = offset + strlen(ip_list) + 1;
offset = offset + strlen(ip_list + offset) + 1;
}
free(ip_list);
log_info("Deleting ip: 192.168.168.168/24");
if (knet_tap_del_ip(knet_tap, "192.168.168.168", "24") < 0) {
log_error("Unable to delete IP address");
err=-1;
goto out_clean;
}
log_info("Deleting ip: 192.168.169.169/24");
if (knet_tap_del_ip(knet_tap, "192.168.169.169", "24") < 0) {
log_error("Unable to delete IP address");
err=-1;
goto out_clean;
}
log_info("Deleting again ip: 192.168.168.168/24");
if (knet_tap_del_ip(knet_tap, "192.168.168.168", "24") < 0) {
log_error("Unable to delete IP address");
err=-1;
goto out_clean;
}
- log_info("A shell error here is NORMAL");
- if (!tap_execute_shell("ip addr show dev kronostest | grep -q 192.168.168.168/24")) {
+ err = tap_execute_shell("ip addr show dev kronostest | grep -q 192.168.168.168/24", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Unable to verify IP address");
err=-1;
goto out_clean;
}
log_info("Adding ip: 3ffe::1/64");
if (knet_tap_add_ip(knet_tap, "3ffe::1", "64") < 0) {
log_error("Unable to assign IP address");
err=-1;
goto out_clean;
}
- if (tap_execute_shell("ip addr show dev kronostest | grep -q 3ffe::1/64")) {
+ err = tap_execute_shell("ip addr show dev kronostest | grep -q 3ffe::1/64", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (err) {
log_error("Unable to verify IP address");
err=-1;
goto out_clean;
}
log_info("Deleting ip: 3ffe::1/64");
if (knet_tap_del_ip(knet_tap, "3ffe::1", "64") < 0) {
log_error("Unable to delete IP address");
err=-1;
goto out_clean;
}
- log_info("A shell error here is NORMAL");
- if (!tap_execute_shell("ip addr show dev kronostest | grep -q 3ffe::1/64")) {
+ err = tap_execute_shell("ip addr show dev kronostest | grep -q 3ffe::1/64", &error_string);
+ if (error_string) {
+ log_error("Error string: %s", error_string);
+ free(error_string);
+ error_string = NULL;
+ }
+ if (!err) {
log_error("Unable to verify IP address");
err=-1;
goto out_clean;
}
out_clean:
knet_tap_close(knet_tap);
return err;
}
int main(void)
{
if (check_knet_tap_open_close() < 0)
return -1;
if (check_knet_multi_eth() < 0)
return -1;
if (check_knet_mtu() < 0)
return -1;
if (check_knet_mac() < 0)
return -1;
if (check_tap_execute_shell() < 0)
return -1;
if (check_knet_up_down() < 0)
return -1;
if (check_knet_set_del_ip() < 0)
return -1;
if (check_knet_close_leak() < 0)
return -1;
return 0;
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Dec 23, 12:27 PM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1128340
Default Alt Text
(39 KB)

Event Timeline