1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#include <arpa/inet.h>
#include <linux/rtnetlink.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"
#include "xlib.h"
static struct list_head host_list = LIST_INITIALIZER(host_list);
static void execute_action(const char *action)
{
pid_t pid;
const char *shell = getenv("SHELL");
if (shell == NULL)
shell = "/bin/sh";
log_debug("executing '%s'", action);
pid = fork();
if (pid < 0) {
log_perror("fork");
return;
}
if (pid == 0) {
execl(shell, shell, "-c", action, NULL);
log_perror(action);
exit(1);
}
}
int pingu_host_set_status(struct pingu_host *host, int status)
{
const char *action;
int route_action = 0;
host->burst.active = 0;
if (host->status == status) {
log_debug("%s: status is still %i", host->label, status);
return status;
}
host->status = status;
log_info("%s: new status: %i", host->label, status);
switch (host->status) {
case 0:
action = host->down_action;
route_action = RTM_DELROUTE;
break;
case 1:
action = host->up_action;
route_action = RTM_NEWROUTE;
break;
}
if (action != NULL)
execute_action(action);
pingu_iface_update_routes(host->iface, route_action);
return status;
}
int pingu_host_verify_status(struct ev_loop *loop, struct pingu_host *host)
{
if (host->burst.pings_replied >= host->required_replies) {
pingu_host_set_status(host, 1);
} else if (host->burst.pings_sent >= host->max_retries) {
pingu_host_set_status(host, 0);
} else
pingu_ping_send(loop, host, 1);
return 0;
}
struct pingu_host *pingu_host_new(char *hoststr, float burst_interval,
int max_retries, int required_replies,
float timeout,
const char *up_action,
const char *down_action)
{
struct pingu_host *host = calloc(1, sizeof(struct pingu_host));
if (host == NULL) {
log_perror(hoststr);
return NULL;
}
host->host = hoststr;
host->status = 1; /* online by default */
host->burst_interval = burst_interval;
host->max_retries = max_retries;
host->required_replies = required_replies;
host->timeout = timeout;
host->up_action = up_action;
host->down_action = down_action;
list_add(&host->host_list_entry, &host_list);
return host;
}
int pingu_host_init(struct ev_loop *loop)
{
struct pingu_host *host;
list_for_each_entry(host, &host_list, host_list_entry) {
if (host->label == NULL)
host->label = host->host;
ev_timer_init(&host->burst_timeout_watcher,
pingu_burst_timeout_cb, 0, host->burst_interval);
ev_timer_start(loop, &host->burst_timeout_watcher);
}
return 0;
}
|