diff options
author | Natanael Copa <ncopa@alpinelinux.org> | 2011-07-07 14:31:32 +0200 |
---|---|---|
committer | Natanael Copa <ncopa@alpinelinux.org> | 2011-07-07 14:34:26 +0200 |
commit | 69c10bc4bf9b1d98a9a0b5860d10cf5fc3b40aa9 (patch) | |
tree | 9d5a1cada739de106cca5ba64b7ad2969934a87d | |
parent | 22c01818744c1fd386d5d943afe6fda0a51396ed (diff) | |
download | pingu-69c10bc4bf9b1d98a9a0b5860d10cf5fc3b40aa9.tar.bz2 pingu-69c10bc4bf9b1d98a9a0b5860d10cf5fc3b40aa9.tar.xz |
iface: add initial implementation
-rw-r--r-- | pingu_iface.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/pingu_iface.c b/pingu_iface.c new file mode 100644 index 0000000..6dca73c --- /dev/null +++ b/pingu_iface.c @@ -0,0 +1,104 @@ + +#include <sys/socket.h> +#include <arpa/inet.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +#include <ev.h> + +#include "list.h" +#include "log.h" +#include "pingu_burst.h" +#include "pingu_host.h" +#include "pingu_iface.h" +#include "pingu_ping.h" + +static struct list_head iface_list = LIST_INITIALIZER(iface_list); + +static void pingu_iface_socket_cb(struct ev_loop *loop, struct ev_io *w, + int revents) +{ + struct pingu_iface *iface = container_of(w, struct pingu_iface, socket_watcher); + + if (revents & EV_READ) + pingu_ping_read_reply(loop, iface); +} + +static int pingu_iface_init_socket(struct ev_loop *loop, + struct pingu_iface *iface) +{ + int r; + iface->fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (iface->fd < 0) { + log_perror("socket"); + return -1; + } + + ev_io_init(&iface->socket_watcher, pingu_iface_socket_cb, iface->fd, EV_READ); + ev_io_start(loop, &iface->socket_watcher); + + if (iface->name[0] == '\0') + return 0; + r = setsockopt(iface->fd, SOL_SOCKET, SO_BINDTODEVICE, iface->name, + strlen(iface->name)); + if (r < 0) { + log_perror(iface->name); + return -1; + } + return 0; +} + +struct pingu_iface *pingu_iface_find(const char *name) +{ + struct pingu_iface *iface; + list_for_each_entry(iface, &iface_list, iface_list_entry) { + if (name == NULL) { + if (iface->name[0] == '\n') + return iface; + } else if (strncmp(name, iface->name, sizeof(iface->name)) == 0) + return iface; + } + return NULL; +} + +struct pingu_iface *pingu_iface_find_or_create(struct ev_loop *loop, const char *name) +{ + struct pingu_iface *iface = pingu_iface_find(name); + if (iface != NULL) + return iface; + + iface = calloc(1, sizeof(struct pingu_iface)); + if (iface == NULL) { + log_perror("calloc(iface)"); + return NULL; + } + + if (name != NULL) + strlcpy(iface->name, name, sizeof(*iface->name)); + + if (pingu_iface_init_socket(loop, iface) == -1) { + free(iface); + return NULL; + } + list_init(&iface->ping_list); + list_add(&iface->iface_list_entry, &iface_list); + return iface; +} + +int pingu_iface_init(struct ev_loop *loop, struct list_head *host_list) +{ + struct pingu_host *host; + struct pingu_iface *iface; + list_for_each_entry(host, host_list, host_list_entry) { + iface = pingu_iface_find_or_create(loop, host->interface); + if (iface == NULL) + return -1; + host->iface = iface; + } + return 0; +} + |