Put all the arrays in `ping.c' into one struct.
[collectd.git] / src / ping.c
1 /**
2  * collectd - src/ping.c
3  * Copyright (C) 2005  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  * Authors:
20  *   Florian octo Forster <octo at verplant.org>
21  **/
22
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
26 #include "configfile.h"
27
28 #define MODULE_NAME "ping"
29
30 #include <netinet/in.h>
31 #include "libping/ping.h"
32
33 #define MAX_PINGHOSTS 32
34
35 typedef struct
36 {
37         char *name;
38         int   flags;
39         int   disable; /* How long (how many iterations) this host is still disabled */
40         int   backoff; /* How long the host will be disabled, if it failes again */
41 } pinghost_t;
42
43 static pinghost_t hosts[MAX_PINGHOSTS];
44 static int        num_pinghosts;
45
46 static char *file_template = "ping-%s.rrd";
47
48 static char *ds_def[] = 
49 {
50         "DS:ping:GAUGE:25:0:65535",
51         NULL
52 };
53 static int ds_num = 1;
54
55 static char *config_keys[] =
56 {
57         "Host",
58         NULL
59 };
60 static int config_keys_num = 1;
61
62 static void ping_init (void)
63 {
64         int i;
65
66         for (i = 0; i < MAX_PINGHOSTS; i++)
67         {
68                 hosts[i].flags = 0;
69                 hosts[i].disable = 0;
70                 hosts[i].backoff = 1;
71         }
72
73         return;
74 }
75
76 static int ping_config (char *key, char *value)
77 {
78         if (strcasecmp (key, "host"))
79         {
80                 return (-1);
81         }
82         else if (num_pinghosts >= MAX_PINGHOSTS)
83         {
84                 return (1);
85         }
86         else if ((hosts[num_pinghosts].name = strdup (value)) == NULL)
87         {
88                 return (2);
89         }
90         else
91         {
92                 num_pinghosts++;
93                 return (0);
94         }
95 }
96
97 static void ping_write (char *host, char *inst, char *val)
98 {
99         char file[512];
100         int status;
101
102         status = snprintf (file, 512, file_template, inst);
103         if (status < 1)
104                 return;
105         else if (status >= 512)
106                 return;
107
108         rrd_update_file (host, file, val, ds_def, ds_num);
109 }
110
111 #define BUFSIZE 256
112 static void ping_submit (int ping_time, char *host)
113 {
114         char buf[BUFSIZE];
115
116         if (snprintf (buf, BUFSIZE, "%u:%i", (unsigned int) curtime, ping_time) >= BUFSIZE)
117                 return;
118
119         plugin_submit (MODULE_NAME, host, buf);
120 }
121 #undef BUFSIZE
122
123 static void ping_read (void)
124 {
125         int ping;
126         int i;
127
128         for (i = 0; i < num_pinghosts; i++)
129         {
130                 if (hosts[i].disable > 0)
131                 {
132                         hosts[i].disable--;
133                         continue;
134                 }
135                 
136                 ping = tpinghost (hosts[i].name);
137
138                 switch (ping)
139                 {
140                         case 0:
141                                 if (!(hosts[i].flags & 0x01))
142                                         syslog (LOG_WARNING, "ping %s: Connection timed out.", hosts[i].name);
143                                 hosts[i].flags |= 0x01;
144                                 break;
145
146                         case -1:
147                                 if (!(hosts[i].flags & 0x02))
148                                         syslog (LOG_WARNING, "ping %s: Host or service is not reachable.", hosts[i].name);
149                                 hosts[i].flags |= 0x02;
150                                 break;
151
152                         case -2:
153                                 syslog (LOG_ERR, "ping %s: Socket error. Ping will be disabled for %i iteration(s).",
154                                                 hosts[i].name, hosts[i].backoff);
155                                 hosts[i].disable = hosts[i].backoff;
156                                 if (hosts[i].backoff < 8192) /* 22 3/4 hours */
157                                         hosts[i].backoff *= 2;
158                                 hosts[i].flags |= 0x10;
159                                 break;
160
161                         case -3:
162                                 if (!(hosts[i].flags & 0x04))
163                                         syslog (LOG_WARNING, "ping %s: Connection refused.", hosts[i].name);
164                                 hosts[i].flags |= 0x04;
165                                 break;
166
167                         default:
168                                 if (hosts[i].flags != 0x00)
169                                         syslog (LOG_NOTICE, "ping %s: Back to normal: %ims.", hosts[i].name, ping);
170                                 hosts[i].flags = 0x00;
171                                 hosts[i].backoff = 1;
172                                 ping_submit (ping, hosts[i].name);
173                 } /* switch (ping) */
174         } /* for (i = 0; i < num_pinghosts; i++) */
175 }
176
177 void module_register (void)
178 {
179         plugin_register (MODULE_NAME, ping_init, ping_read, ping_write);
180         cf_register (MODULE_NAME, ping_config, config_keys, config_keys_num);
181 }
182
183 #undef MODULE_NAME