summaryrefslogtreecommitdiffstats
path: root/web/attachments/121773-check_icmp-bundled.diff
diff options
context:
space:
mode:
Diffstat (limited to 'web/attachments/121773-check_icmp-bundled.diff')
-rw-r--r--web/attachments/121773-check_icmp-bundled.diff742
1 files changed, 742 insertions, 0 deletions
diff --git a/web/attachments/121773-check_icmp-bundled.diff b/web/attachments/121773-check_icmp-bundled.diff
new file mode 100644
index 0000000..4bb56b4
--- /dev/null
+++ b/web/attachments/121773-check_icmp-bundled.diff
@@ -0,0 +1,742 @@
1diff -urN ../plugins/plugins/check_icmp.c ./plugins/check_icmp.c
2--- ../plugins/plugins/check_icmp.c 2005-02-01 15:31:11.000000000 +0100
3+++ ./plugins/check_icmp.c 2005-02-18 15:57:08.000000000 +0100
4@@ -1,5 +1,5 @@
5 /*
6- * $Id: check_icmp.c,v 1.5 2005/02/01 07:33:13 stanleyhopcroft Exp $
7+ * $Id: check_icmp.c,v 1.12 2005/01/29 23:23:23 exon Exp $
8 *
9 * Author: Andreas Ericsson <ae@op5.se>
10 *
11@@ -14,6 +14,15 @@
12 * redundant routes. The only remainders of fping is currently a few
13 * function names.
14 *
15+ * Kudos to;
16+ * Joe Rhett
17+ * Wickus Botha
18+ * Aaron Carr
19+ * Harper Mann
20+ * Phil Costelloe
21+ * Carsten Schmitz
22+ * for lending me system resources, testing and feedback
23+ *
24 */
25
26 #include <sys/time.h>
27@@ -84,7 +93,7 @@
28 char *msg; /* icmp error message, if any */
29 struct sockaddr_in saddr_in; /* the address of this host */
30 struct in_addr error_addr; /* stores address of error replies */
31- unsigned long long time_waited; /* total time waited, in usecs */
32+ unsigned long int time_waited; /* total time waited, in usecs */
33 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
34 unsigned char icmp_type, icmp_code; /* type and code from errors */
35 unsigned short flags; /* control/status flags */
36@@ -137,18 +146,19 @@
37 #define IP_HDR_SIZE 20
38 #define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN)
39 #define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44)
40+#define DEFAULT_TTL 64
41
42-/* various target states */
43-#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */
44-#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */
45-#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */
46-#define TSTATE_UNREACH 0x08
47+#define MIN_PKT_INTERVAL 25000 /* min pkt_interval, microsecs */
48+#define NOFORCE_WAIT 0
49+#define FORCE_WAIT 1
50
51 /** prototypes **/
52-static void usage(unsigned char, char *);
53+static void usage(unsigned char, char *, ...);
54 static u_int get_timevar(const char *);
55 static u_int get_timevaldiff(struct timeval *, struct timeval *);
56-static int wait_for_reply(int, u_int);
57+static int reap_replies(int, u_int, int);
58+void u_sleep(u_int u_sec);
59+static u_int wait_for_reply(int, u_int);
60 static int recvfrom_wto(int, char *, unsigned int, struct sockaddr *, u_int *);
61 static int send_icmp_ping(int, struct rta_host *);
62 static int get_threshold(char *str, threshold *th);
63@@ -162,6 +172,7 @@
64
65 /** external **/
66 extern int optind, opterr, optopt;
67+/* extern int h_errno; */
68 extern char *optarg;
69 extern char **environ;
70
71@@ -173,15 +184,15 @@
72 static unsigned short icmp_pkt_size, icmp_data_size = DEFAULT_PING_DATA_SIZE;
73 static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0;
74 #define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost))
75-static unsigned short targets_down = 0, targets = 0, packets = 0;
76+static unsigned int targets_down = 0, targets = 0, packets = 0;
77 #define targets_alive (targets - targets_down)
78 static unsigned int retry_interval, pkt_interval, target_interval;
79 static int icmp_sock, tcp_sock, udp_sock, status = STATE_OK;
80 static pid_t pid;
81 static struct timezone tz;
82 static struct timeval prog_start;
83-static unsigned long long max_completion_time = 0;
84-static unsigned char ttl = 0; /* outgoing ttl */
85+static unsigned long int max_completion_time = 0;
86+static unsigned char ttl = 64; /* outgoing ttl */
87 static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */
88 float pkt_backoff_factor = 1.5;
89 float target_backoff_factor = 1.5;
90@@ -210,7 +221,8 @@
91 {
92 char *msg = "unreachable";
93
94- if(debug > 1) printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code);
95+ if(debug > 3) printf("get_icmp_error_msg(%u, %u) called\n",
96+ icmp_type, icmp_code);
97 switch(icmp_type) {
98 case ICMP_UNREACH:
99 switch(icmp_code) {
100@@ -269,7 +281,7 @@
101 unsigned char *ptr;
102
103 if(p->icmp_type == ICMP_ECHO && p->icmp_id == pid) {
104- /* echo request from us to us (pinging localhost) */
105+ if(debug > 2) printf("echo request from us to us (pinging localhost)\n");
106 return 0;
107 }
108
109@@ -286,9 +298,13 @@
110 * TIMXCEED actually sends a proper icmp response we will have passed
111 * too many hops to have a hope of reaching it later, in which case it
112 * indicates overconfidence in the network, poor routing or both. */
113+ if(debug > 2) printf("random ICMP response type: %u, code: %u\n",
114+ p->icmp_type, p->icmp_code);
115 if(p->icmp_type != ICMP_UNREACH && p->icmp_type != ICMP_TIMXCEED &&
116 p->icmp_type != ICMP_SOURCEQUENCH && p->icmp_type != ICMP_PARAMPROB)
117 {
118+ if(debug > 1) printf("Unsafe to handle unknown type %u, returning\n",
119+ p->icmp_type);
120 return 0;
121 }
122
123@@ -298,7 +314,7 @@
124 if(sent_icmp->icmp_type != ICMP_ECHO || sent_icmp->icmp_id != pid ||
125 sent_icmp->icmp_seq >= targets)
126 {
127- if(debug) printf("Packet is no response to a packet we sent\n");
128+ if(debug) printf("not a response to a packet we sent, or target failed to duplicate request\n");
129 return 0;
130 }
131
132@@ -394,12 +410,12 @@
133 }
134 else if(!strcmp(progname, "check_host")) {
135 mode = MODE_HOSTCHECK;
136- pkt_interval = 1000000;
137+ pkt_interval = 200000;
138 packets = 5;
139 crit.rta = warn.rta = 1000000;
140 crit.pl = warn.pl = 100;
141 }
142- else if(!strcmp(progname, "check_rta_multi")) {
143+ else if(!strcmp(progname, "check_icmp_multi")) {
144 mode = MODE_ALL;
145 target_interval = 0;
146 pkt_interval = 50000;
147@@ -408,6 +424,8 @@
148
149 /* parse the arguments */
150 for(i = 1; i < argc; i++) {
151+ /* the leading '-' of the optstring makes non-argument options
152+ * return with arg 1, meaning it's */
153 while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:i:b:I:l:")) != EOF) {
154 switch(arg) {
155 case 'v':
156@@ -436,7 +454,8 @@
157 timeout = strtoul(optarg, NULL, 0);
158 if(!timeout) timeout = 10;
159 break;
160- case 'H':
161+ case 'H': case 1: /* 1 is default for non-option arguments */
162+ /* printf("arg: %ld, optarg: %s\n", arg, optarg); */
163 add_target(optarg);
164 break;
165 case 'l':
166@@ -460,11 +479,10 @@
167 add_target(*argv);
168 argv++;
169 }
170- if(!targets) {
171- errno = 0;
172- crash("No hosts to check");
173- exit(3);
174- }
175+ if(!targets) usage('h', "No hosts to check");
176+
177+ if(getuid() && pkt_interval < MIN_PKT_INTERVAL)
178+ pkt_interval = MIN_PKT_INTERVAL;
179
180 if(!sockets) {
181 if(icmp_sock == -1) {
182@@ -486,10 +504,12 @@
183 if(!ttl) ttl = 64;
184
185 if(icmp_sock) {
186+ errno = 0;
187 result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl));
188 if(debug) {
189- if(result == -1) printf("setsockopt failed\n");
190- else printf("ttl set to %u\n", ttl);
191+ printf("setsockopt(icmp_sock, SOL_IP, IP_TTL, %u) = %d (%s)\n",
192+ ttl, result, strerror(errno));
193+ if(result != -1) printf("outgoing ttl set to %u\n", ttl);
194 }
195 }
196
197@@ -505,7 +525,7 @@
198 signal(SIGHUP, finish);
199 signal(SIGTERM, finish);
200 signal(SIGALRM, finish);
201- if(debug) printf("Setting alarm timeout to %u seconds\n", timeout);
202+ if(debug > 1) printf("Setting alarm timeout to %u seconds\n", timeout);
203 alarm(timeout);
204
205 /* make sure we don't wait any longer than necessary */
206@@ -514,10 +534,9 @@
207 ((targets * packets * pkt_interval) + (targets * target_interval)) +
208 (targets * packets * crit.rta) + crit.rta;
209
210- if(debug) {
211+ if(debug > 1) {
212 printf("packets: %u, targets: %u\n"
213- "target_interval: %0.3f, pkt_interval %0.3f\n"
214- "crit.rta: %0.3f\n"
215+ "target_interval: %0.3f, pkt_interval %0.3f, crit.rta: %0.3f\n"
216 "max_completion_time: %0.3f\n",
217 packets, targets,
218 (float)target_interval / 1000, (float)pkt_interval / 1000,
219@@ -527,9 +546,9 @@
220
221 if(debug) {
222 if(max_completion_time > (u_int)timeout * 1000000) {
223- printf("max_completion_time: %llu timeout: %u\n",
224+ printf("max_completion_time: %lu timeout: %u\n",
225 max_completion_time, timeout);
226- printf("Timout must be at lest %llu\n",
227+ printf("Timout must be at lest %lu\n",
228 max_completion_time / 1000000 + 1);
229 }
230 }
231@@ -579,24 +598,27 @@
232 u_int i, t, result;
233 u_int final_wait, time_passed;
234
235- /* this loop might actually violate the pkt_interval or target_interval
236- * settings, but only if there aren't any packets on the wire which
237- * indicates that the target can handle an increased packet rate */
238- for(i = 0; i < packets; i++) {
239- for(t = 0; t < targets; t++) {
240+ /* send the packets */
241+ for(t = 0; t < targets; t++) {
242+ for(i = 0; i < packets; i++) {
243+
244 /* don't send useless packets */
245- if(!targets_alive) finish(0);
246 if(table[t]->flags & FLAG_LOST_CAUSE) {
247 if(debug) printf("%s is a lost cause. not sending any more\n",
248 table[t]->name);
249 continue;
250 }
251-
252+
253 /* we're still in the game, so send next packet */
254 (void)send_icmp_ping(icmp_sock, table[t]);
255- result = wait_for_reply(icmp_sock, target_interval);
256+
257+ /* pause for a while so we don't flood the network */
258+ result = reap_replies(icmp_sock, pkt_interval, FORCE_WAIT);
259 }
260- result = wait_for_reply(icmp_sock, pkt_interval * targets);
261+
262+ /* wait for all incoming packets from all hosts */
263+ if(target_interval > pkt_interval)
264+ result = reap_replies(icmp_sock, target_interval - pkt_interval, FORCE_WAIT);
265 }
266
267 if(icmp_pkts_en_route && targets_alive) {
268@@ -604,7 +626,7 @@
269 final_wait = max_completion_time - time_passed;
270
271 if(debug) {
272- printf("time_passed: %u final_wait: %u max_completion_time: %llu\n",
273+ printf("time_passed: %u final_wait: %u max_completion_time: %lu\n",
274 time_passed, final_wait, max_completion_time);
275 }
276 if(time_passed > max_completion_time) {
277@@ -616,8 +638,61 @@
278 * haven't yet */
279 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n",
280 final_wait, (float)final_wait / 1000);
281- result = wait_for_reply(icmp_sock, final_wait);
282+ result = reap_replies(icmp_sock, final_wait, NOFORCE_WAIT);
283+ }
284+}
285+
286+/*
287+ * select() is posix, so we expect it to be around
288+ */
289+void
290+u_sleep(u_int u_sec)
291+{
292+ int nfound;
293+ struct timeval to;
294+ fd_set readset, writeset;
295+
296+ if(debug > 3) printf("sleeping for %u microseconds\n", u_sec);
297+ if(!u_sec) return;
298+
299+ to.tv_sec = u_sec / 1000000;
300+ to.tv_usec = u_sec % 1000000;
301+ FD_ZERO(&writeset);
302+ FD_ZERO(&readset);
303+ nfound = select(0, &readset, &writeset, NULL, &to);
304+ if(nfound < 0)
305+ crash("select() in u_sleep");
306+
307+ return;
308+} /* u_sleep() */
309+
310+static int
311+reap_replies(int sock, u_int t, int wait_forced)
312+{
313+ /* wrap up if all targets are declared dead */
314+ if(debug > 3) printf("reap_replies(%d, %u, %d) called\n", sock, t, wait_forced);
315+
316+ if(!targets_alive ||
317+ get_timevaldiff(&prog_start, NULL) >= max_completion_time)
318+ {
319+ finish(0);
320+ }
321+
322+ /* listen til timeout while there are packets en route (rhymes!) ;) */
323+ while(t && icmp_pkts_en_route) {
324+ t = wait_for_reply(sock, t);
325+
326+ /* the dead won't sing to us */
327+ if(!targets_alive) finish(0);
328 }
329+
330+ if(icmp_recv == (targets_alive * (int)packets)) finish(0);
331+
332+ if(!t || !wait_forced) return 0;
333+
334+ u_sleep(t);
335+
336+ return 0;
337 }
338
339 /* response structure:
340@@ -625,126 +700,98 @@
341 * icmp header : 28 bytes
342 * icmp echo reply : the rest
343 */
344-static int
345+static u_int
346 wait_for_reply(int sock, u_int t)
347 {
348 int n, hlen;
349 static char buf[4096];
350 struct sockaddr_in resp_addr;
351 struct ip *ip;
352- struct icmp *icp, *sent_icmp;
353+ struct icmp *icp;
354 struct rta_host *host;
355 struct icmp_ping_data *data;
356 struct timeval wait_start, now;
357- u_int tdiff, i, per_pkt_wait;
358-
359- /* if we can't listen or don't have anything to listen to, just return */
360- if(!t || !icmp_pkts_en_route) return 0;
361+ u_int tdiff, timo = t;
362
363 gettimeofday(&wait_start, &tz);
364
365- i = t;
366- per_pkt_wait = t / icmp_pkts_en_route;
367- while(icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) {
368- t = per_pkt_wait;
369-
370- /* wrap up if all targets are declared dead */
371- if(!targets_alive ||
372- get_timevaldiff(&prog_start, NULL) >= max_completion_time ||
373- (mode == MODE_HOSTCHECK && targets_down))
374- {
375- finish(0);
376- }
377+ n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &timo);
378+ if(!n) { /* timeout */
379+ if(debug > 2) printf("recvfrom_wto() timed out during a %u usecs wait\n", t);
380+ return 0; /* no time left, so return just that */
381+ }
382
383- /* reap responses until we hit a timeout */
384- n = recvfrom_wto(sock, buf, sizeof(buf),
385- (struct sockaddr *)&resp_addr, &t);
386- if(!n) {
387- if(debug > 1) {
388- printf("recvfrom_wto() timed out during a %u usecs wait\n",
389- per_pkt_wait);
390- }
391- continue; /* timeout for this one, so keep trying */
392- }
393- if(n < 0) {
394- if(debug) printf("recvfrom_wto() returned errors\n");
395- return n;
396- }
397+ gettimeofday(&now, &tz);
398+ tdiff = get_timevaldiff(&wait_start, &now);
399+ /* make sure we can return time left */
400+ if(t > tdiff) t -= tdiff;
401+ else t = 0;
402
403- ip = (struct ip *)buf;
404- if(debug > 1) printf("received %u bytes from %s\n",
405+ ip = (struct ip *)buf;
406+ if(debug > 1) printf("received %u bytes from %s\n",
407 ntohs(ip->ip_len), inet_ntoa(resp_addr.sin_addr));
408
409-/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */
410+/* obsolete, or at least not globally applicable */
411 /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */
412 /* alpha headers are decidedly broken. Using an ansi compiler,
413 * they provide ip_vhl instead of ip_hl and ip_v, so we mask
414 * off the bottom 4 bits */
415 /* hlen = (ip->ip_vhl & 0x0f) << 2; */
416 /* #else */
417- hlen = ip->ip_hl << 2;
418+ hlen = ip->ip_hl << 2;
419 /* #endif */
420
421- if(n < (hlen + ICMP_MINLEN)) {
422- crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n",
423- n, hlen + icmp_pkt_size, inet_ntoa(resp_addr.sin_addr));
424- }
425- /* else if(debug) { */
426- /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */
427- /* hlen, ntohs(ip->ip_len) - hlen, */
428- /* sizeof(struct ip), icmp_pkt_size); */
429- /* } */
430-
431- /* check the response */
432- icp = (struct icmp *)(buf + hlen);
433- sent_icmp = (struct icmp *)(buf + hlen + ICMP_MINLEN);
434- /* printf("buf: %p, icp: %p, distance: %u (expected %u)\n", */
435- /* buf, icp, */
436- /* (u_int)icp - (u_int)buf, hlen); */
437- /* printf("buf: %p, sent_icmp: %p, distance: %u (expected %u)\n", */
438- /* buf, sent_icmp, */
439- /* (u_int)sent_icmp - (u_int)buf, hlen + ICMP_MINLEN); */
440-
441- if(icp->icmp_id != pid) {
442- handle_random_icmp(icp, &resp_addr);
443- continue;
444- }
445-
446- if(icp->icmp_type != ICMP_ECHOREPLY || icp->icmp_seq >= targets) {
447- if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n");
448- handle_random_icmp(icp, &resp_addr);
449- continue;
450- }
451-
452- /* this is indeed a valid response */
453- data = (struct icmp_ping_data *)(icp->icmp_data);
454-
455- host = table[icp->icmp_seq];
456- gettimeofday(&now, &tz);
457- tdiff = get_timevaldiff(&data->stime, &now);
458+ if(n < (hlen + ICMP_MINLEN)) {
459+ crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n",
460+ n, hlen + icmp_pkt_size, inet_ntoa(resp_addr.sin_addr));
461+ }
462+ else if(debug > 2) {
463+ printf("ip header size: %u, packet size: %u (expected %u, %u)\n",
464+ hlen, ntohs(ip->ip_len) - hlen,
465+ sizeof(struct ip), (u_int)icmp_pkt_size);
466+ }
467
468- host->time_waited += tdiff;
469- host->icmp_recv++;
470- icmp_recv++;
471+ /* check the response */
472+ icp = (struct icmp *)(buf + hlen);
473
474+ if(icp->icmp_id != pid || icp->icmp_type != ICMP_ECHOREPLY || icp->icmp_seq >= targets) {
475 if(debug) {
476- printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u\n",
477- (float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr),
478- ttl, ip->ip_ttl);
479- }
480+ printf("inbound packet is:\n");
481+ if(icp->icmp_id != pid) printf("\tnot marked by me\n");
482+ if(icp->icmp_type != ICMP_ECHOREPLY) printf("\tnot an echo reply\n");
483+ if(icp->icmp_seq >= targets) printf("\ttagged with a too high seq number\n");
484+ }
485+ handle_random_icmp(icp, &resp_addr);
486+ return t;
487+ }
488+ if(debug > 2) puts("inbound packet is a valid ICMP_ECHOREPLY to a packet we sent");
489+
490+ /* this is indeed a valid response */
491+ data = (struct icmp_ping_data *)(icp->icmp_data);
492+ host = table[icp->icmp_seq];
493+ tdiff = get_timevaldiff(&data->stime, &now);
494+
495+ host->time_waited += tdiff;
496+ host->icmp_recv++;
497+ icmp_recv++;
498
499- /* if we're in hostcheck mode, exit with limited printouts */
500- if(mode == MODE_HOSTCHECK) {
501- printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
502- "pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
503- host->name, icmp_recv, (float)tdiff / 1000,
504- icmp_recv, packets, (float)tdiff / 1000,
505- (float)warn.rta / 1000, (float)crit.rta / 1000);
506- exit(STATE_OK);
507- }
508+ if(debug) {
509+ printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u\n",
510+ (float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr),
511+ ttl, ip->ip_ttl);
512+ }
513+
514+ /* if we're in hostcheck mode, exit with limited printouts */
515+ if(mode == MODE_HOSTCHECK) {
516+ printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
517+ "pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
518+ host->name, icmp_recv, (float)tdiff / 1000,
519+ icmp_recv, packets, (float)tdiff / 1000,
520+ (float)warn.rta / 1000, (float)crit.rta / 1000);
521+ exit(STATE_OK);
522 }
523
524- return 0;
525+ return t;
526 }
527
528 /* the ping functions */
529@@ -776,8 +823,6 @@
530 }
531 memset(buf, 0, icmp_pkt_size + sizeof(struct ip));
532
533- if((gettimeofday(&tv, &tz)) == -1) return -1;
534-
535 icp = (struct icmp *)buf;
536 icp->icmp_type = ICMP_ECHO;
537 icp->icmp_code = 0;
538@@ -785,7 +830,9 @@
539 icp->icmp_id = pid;
540 icp->icmp_seq = host->id;
541 data = (struct icmp_ping_data *)icp->icmp_data;
542- data->ping_id = 10; /* host->icmp.icmp_sent; */
543+ data->ping_id = host->icmp_sent;
544+
545+ if((gettimeofday(&tv, &tz)) == -1) return -1;
546 memcpy(&data->stime, &tv, sizeof(struct timeval));
547 icp->icmp_cksum = icmp_checksum((u_short *)icp, icmp_pkt_size);
548
549@@ -798,6 +845,7 @@
550 return -1;
551 }
552
553+ /* increment the counters */
554 icmp_sent++;
555 host->icmp_sent++;
556
557@@ -809,7 +857,7 @@
558 u_int *timo)
559 {
560 u_int slen;
561- int n;
562+ int n, result;
563 struct timeval to, then, now;
564 fd_set rd, wr;
565
566@@ -835,7 +883,10 @@
567
568 slen = sizeof(struct sockaddr);
569
570- return recvfrom(sock, buf, len, 0, saddr, &slen);
571+ result = recvfrom(sock, buf, len, 0, saddr, &slen);
572+ if(result < 0) crash("recvfrom in recvfrom_wto");
573+
574+ return result;
575 }
576
577 static void
578@@ -849,7 +900,7 @@
579 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
580
581 alarm(0);
582- if(debug > 1) printf("finish(%d) called\n", sig);
583+ if(debug > 2) printf("finish(%d) called\n", sig);
584
585 if(icmp_sock != -1) close(icmp_sock);
586 if(udp_sock != -1) close(udp_sock);
587@@ -1016,23 +1067,20 @@
588 struct hostent *he;
589 struct in_addr *in, ip;
590
591- /* don't resolve if we don't have to */
592- if((ip.s_addr = inet_addr(arg)) != INADDR_NONE) {
593- /* don't add all ip's if we were given a specific one */
594- return add_target_ip(arg, &ip);
595- /* he = gethostbyaddr((char *)in, sizeof(struct in_addr), AF_INET); */
596- /* if(!he) return add_target_ip(arg, in); */
597- }
598- else {
599- errno = 0;
600+ /* don't resolve if we don't have to, don't add all ip's if we were
601+ * given a specific one, even if we're in hostcheck mode */
602+ if(inet_aton(arg, &ip)) return add_target_ip(arg, &ip);
603+
604+ /* not an IP, so resolve */
605+ errno = 0;
606+ he = gethostbyname(arg);
607+ if(!he && h_errno == TRY_AGAIN) {
608+ u_sleep(500000);
609 he = gethostbyname(arg);
610- if(!he) {
611- errno = 0;
612- crash("Failed to resolve %s", arg);
613- return -1;
614- }
615 }
616
617+ if(!he) usage(0, "Failed to resolve %s: %s", arg, hstrerror(h_errno));
618+
619 /* possibly add all the IP's as targets */
620 for(i = 0; he->h_addr_list[i]; i++) {
621 in = (struct in_addr *)he->h_addr_list[i];
622@@ -1040,7 +1088,7 @@
623
624 /* this is silly, but it works */
625 if(mode == MODE_HOSTCHECK || mode == MODE_ALL) {
626- printf("mode: %d\n", mode);
627+ if(debug) printf("mode: %d\n", mode);
628 continue;
629 }
630 break;
631@@ -1048,6 +1096,7 @@
632
633 return 0;
634 }
635+
636 /*
637 * u = micro
638 * m = milli
639@@ -1073,12 +1122,12 @@
640 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2];
641 if(p && u == 's') u = p;
642 else if(!p) p = u;
643- if(debug > 2) printf("evaluating %s, u: %c, p: %c\n", str, u, p);
644+ if(debug > 3) printf("evaluating %s, u: %c, p: %c\n", str, u, p);
645
646 if(u == 'u') factor = 1; /* microseconds */
647 else if(u == 'm') factor = 1000; /* milliseconds */
648 else if(u == 's') factor = 1000000; /* seconds */
649- if(debug > 2) printf("factor is %u\n", factor);
650+ if(debug > 3) printf("factor is %u\n", factor);
651
652 i = strtoul(str, &ptr, 0);
653 if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1)
654@@ -1149,51 +1198,58 @@
655
656 /* make core plugin developers happy (silly, really) */
657 static void
658-usage(unsigned char arg, char *msg)
659+usage(unsigned char arg, char *fmt, ...)
660 {
661- if(msg) printf("%s: %s\n", progname, msg);
662+ if(fmt) {
663+ va_list ap;
664+
665+ printf("%s: ", progname);
666+
667+ va_start(ap, fmt);
668+ vprintf(fmt, ap);
669+ va_end(ap);
670+ puts("\n");
671+ }
672
673 if(arg == 'V') {
674- printf("$Id: check_icmp.c,v 1.5 2005/02/01 07:33:13 stanleyhopcroft Exp $\n");
675+ printf("$Id: check_icmp.c,v 1.12 2005/01/29 23:23:23 exon Exp $\n");
676 exit(STATE_UNKNOWN);
677 }
678
679 printf("Usage: %s [options] [-H] host1 host2 hostn\n\n", progname);
680
681- if(arg != 'h') exit(3);
682+ if(arg != 'h') {
683+ printf("%s -h for details\n", progname);
684+ exit(3);
685+ }
686
687 printf("Where options are any combination of:\n"
688- " * -H | --host specify a target\n"
689- " * -w | --warn warning threshold (currently %0.3fms,%u%%)\n"
690- " * -c | --crit critical threshold (currently %0.3fms,%u%%)\n"
691- " * -n | --packets number of packets to send (currently %u)\n"
692- " * -i | --interval max packet interval (currently %0.3fms)\n"
693- " * -I | --hostint max target interval (currently %0.3fms)\n"
694- " * -l | --ttl TTL on outgoing packets (currently %u)\n"
695- " * -t | --timeout timeout value (seconds, currently %u)\n"
696- " * -b | --bytes icmp packet size (currenly ignored)\n"
697- " -v | --verbose verbosity++\n"
698- " -h | --help this cruft\n",
699+ " * -H | --host specify a target\n"
700+ " * -w | --warn warning threshold (currently %0.3fms,%u%%)\n"
701+ " * -c | --crit critical threshold (currently %0.3fms,%u%%)\n"
702+ " * -n | --packets number of packets to send (currently %u)\n"
703+ " * -i | --interval max packet interval (currently %0.3fms)\n"
704+ " * -I | --hostint max target interval (currently %0.3fms)\n",
705 (float)warn.rta / 1000, warn.pl, (float)crit.rta / 1000, crit.pl,
706 packets,
707- (float)pkt_interval / 1000, (float)target_interval / 1000,
708+ (float)pkt_interval / 1000, (float)target_interval / 1000);
709+
710+ printf(" * -l | --ttl outgoing TTL (currently %u, not supported on all platforms)\n"
711+ " * -t | --timeout timeout value (seconds, currently %u)\n"
712+ " * -b | --bytes icmp packet size (currenly ignored)\n"
713+ " -v | --verbose verbosity++ (4 is sort of max)\n"
714+ " -h | --help this cruft\n",
715 ttl, timeout);
716
717- puts("\nThe -H switch is optional. Naming a host (or several) to check is not.\n\n"
718- "Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%\n"
719- "packet loss. The default values should work well for most users.\n"
720+ puts("\nThreshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%\n"
721+ "packet loss. All threshold values match inclusively.\n"
722 "You can specify different RTA factors using the standardized abbreviations\n"
723- "us (microseconds), ms (milliseconds, default) or just plain s for seconds.\n\n"
724- "Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops\n"
725- "are spent and CRITICAL if >= 14 hops are spent.\n"
726- "NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not.\n\n"
727- "The -v switch can be specified several times for increased verbosity.\n\n"
728- "Long options are currently unsupported.\n\n"
729- "Options marked with * require an argument\n");
730-
731- puts("The latest version of this plugin can be found at http://oss.op5.se/nagios\n"
732- "or https://devel.op5.se/oss until the day it is included in the official\n"
733- "plugin distribution.\n");
734+ "us (microseconds), ms (milliseconds, default) or just plain s for seconds.\n");
735+ puts("Long options are currently unsupported.\n");
736+ puts("Options marked with * require an argument\n");
737+ puts("If this program is invoked as check_host (with a symlink, preferrably), it will exit with status\n"
738+ "OK upon the first properly received ICMP_ECHOREPLY, making it ideal\n"
739+ "for hostchecks (less network load and much, much faster on OK)\n");
740
741 exit(3);
742 }