aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pingu_burst.c10
-rw-r--r--pingu_host.c15
-rw-r--r--pingu_host.h2
-rw-r--r--pingu_iface.c26
-rw-r--r--pingu_iface.h2
-rw-r--r--pingu_ping.c9
-rw-r--r--pingu_ping.h3
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