diff options
-rw-r--r-- | pingu_burst.c | 10 | ||||
-rw-r--r-- | pingu_host.c | 15 | ||||
-rw-r--r-- | pingu_host.h | 2 | ||||
-rw-r--r-- | pingu_iface.c | 26 | ||||
-rw-r--r-- | pingu_iface.h | 2 | ||||
-rw-r--r-- | pingu_ping.c | 9 | ||||
-rw-r--r-- | pingu_ping.h | 3 |
7 files changed, 46 insertions, 21 deletions
diff --git a/pingu_burst.c b/pingu_burst.c index 7cc5b9a..3c3fe5b 100644 --- a/pingu_burst.c +++ b/pingu_burst.c @@ -10,12 +10,20 @@ #include "pingu_burst.h" #include "pingu_host.h" #include "pingu_ping.h" +#include "pingu_iface.h" void ping_burst_start(struct ev_loop *loop, struct pingu_host *host) { struct addrinfo hints; struct addrinfo *ai, *rp; int r; + + /* we bind to device every burst in case an iface disappears and + comes back. e.g ppp0 */ + if (pingu_iface_bind_socket(host->iface, host->status) < 0) { + pingu_host_set_status(host, 0); + return; + } host->burst.active = 1; host->burst.pings_sent = 0; @@ -31,7 +39,7 @@ void ping_burst_start(struct ev_loop *loop, struct pingu_host *host) for (rp = ai; rp != NULL; rp = rp->ai_next) { host->burst.saddr = *ai->ai_addr; - r = pingu_ping_send(loop, host); + r = pingu_ping_send(loop, host, 0); if (r == 0) break; } diff --git a/pingu_host.c b/pingu_host.c index ed07487..fae9a0e 100644 --- a/pingu_host.c +++ b/pingu_host.c @@ -213,16 +213,18 @@ static void execute_action(const char *action) } } -void pingu_host_set_status(struct pingu_host *host, int status) +int pingu_host_set_status(struct pingu_host *host, int status) { const char *action; host->burst.active = 0; if (host->status == status) { - log_debug("%s: status is still %i", host->host, status); - return; + log_debug("%s: %s: status is still %i", + host->iface->name, host->host, status); + return status; } host->status = status; - log_info("%s: new status: %i", host->host, status); + log_info("%s: %s: new status: %i", + host->iface->name, host->host, status); switch (host->status) { case 0: action = host->down_action; @@ -234,6 +236,7 @@ void pingu_host_set_status(struct pingu_host *host, int status) if (action != NULL) execute_action(action); exec_route_change(); + return status; } int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host) @@ -243,7 +246,7 @@ int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host) } else if (host->burst.pings_sent >= host->max_retries) { pingu_host_set_status(host, 0); } else - pingu_ping_send(loop, host); + pingu_ping_send(loop, host, 1); return 0; } @@ -257,6 +260,8 @@ int pingu_host_init(struct ev_loop *loop, const char *config) return -1; list_for_each_entry(host, &host_list, host_list_entry) { + if (host->iface->name[0] != '\0' && !host->iface->has_binding) + pingu_host_set_status(host, 0); ev_timer_init(&host->burst_timeout_watcher, pingu_burst_timeout_cb, 0, host->burst_interval); ev_timer_start(loop, &host->burst_timeout_watcher); diff --git a/pingu_host.h b/pingu_host.h index 8ea2831..ba142a6 100644 --- a/pingu_host.h +++ b/pingu_host.h @@ -25,7 +25,7 @@ struct pingu_host { struct pingu_iface *iface; }; -void pingu_host_set_status(struct pingu_host *host, int status); +int pingu_host_set_status(struct pingu_host *host, int status); int pingu_host_init(struct ev_loop *loop, const char *config_file); int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host); diff --git a/pingu_iface.c b/pingu_iface.c index 7b81e44..868c60e 100644 --- a/pingu_iface.c +++ b/pingu_iface.c @@ -27,11 +27,23 @@ static void pingu_iface_socket_cb(struct ev_loop *loop, struct ev_io *w, if (revents & EV_READ) pingu_ping_read_reply(loop, iface); } - + +int pingu_iface_bind_socket(struct pingu_iface *iface, int log_error) +{ + int r; + if (iface->name[0] == '\0') + return 0; + r = setsockopt(iface->fd, SOL_SOCKET, SO_BINDTODEVICE, iface->name, + strlen(iface->name)); + if (r < 0 && log_error) + log_perror(iface->name); + iface->has_binding = (r == 0); + return r; +} + 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"); @@ -40,15 +52,7 @@ static int pingu_iface_init_socket(struct ev_loop *loop, 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; - } + pingu_iface_bind_socket(iface, 1); return 0; } diff --git a/pingu_iface.h b/pingu_iface.h index 99d7362..5bdc587 100644 --- a/pingu_iface.h +++ b/pingu_iface.h @@ -6,6 +6,7 @@ struct pingu_iface { char name[32]; + int has_binding; int fd; struct list_head iface_list_entry; // struct list_head burst_list; @@ -15,6 +16,7 @@ struct pingu_iface { struct pingu_iface *pingu_iface_find(const char *name); struct pingu_iface *pingu_iface_find_or_create(struct ev_loop *loop, const char *name); +int pingu_iface_bind_socket(struct pingu_iface *iface, int log_error); int pingu_iface_init(struct ev_loop *loop, struct list_head *host_list); #endif diff --git a/pingu_ping.c b/pingu_ping.c index 4f15c32..037fb44 100644 --- a/pingu_ping.c +++ b/pingu_ping.c @@ -99,17 +99,22 @@ static void pingu_ping_handle_reply(struct ev_loop *loop, free(ping); } -int pingu_ping_send(struct ev_loop *loop, struct pingu_host *host) +int pingu_ping_send(struct ev_loop *loop, struct pingu_host *host, + int set_status_on_failure) { int packetlen = sizeof(struct iphdr) + sizeof(struct icmphdr); struct pingu_ping *ping; int seq, r; + if ((host->iface->name[0] != '\0') && !host->iface->has_binding) + return pingu_host_set_status(host, 0) - 1; + seq = pingu_ping_get_seq(); r = icmp_send_ping(host->iface->fd, &host->burst.saddr, sizeof(host->burst.saddr), seq, packetlen); if (r < 0) { - pingu_host_set_status(host, 0); + if (set_status_on_failure) + pingu_host_set_status(host, 0); return -1; } diff --git a/pingu_ping.h b/pingu_ping.h index d8f129a..f188748 100644 --- a/pingu_ping.h +++ b/pingu_ping.h @@ -13,7 +13,8 @@ struct pingu_ping { struct ev_timer timeout_watcher; }; -int pingu_ping_send(struct ev_loop *loop, struct pingu_host *host); +int pingu_ping_send(struct ev_loop *loop, struct pingu_host *host, + int set_status_on_failure); void pingu_ping_read_reply(struct ev_loop *loop, struct pingu_iface *iface); #endif |