summaryrefslogtreecommitdiffstats
path: root/plugins-root/check_icmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root/check_icmp.c')
-rw-r--r--plugins-root/check_icmp.c1647
1 files changed, 857 insertions, 790 deletions
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index f788d428..dcaceddb 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -1,45 +1,45 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_icmp plugin 3 * Monitoring check_icmp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2005-2008 Monitoring Plugins Development Team 6 * Copyright (c) 2005-2024 Monitoring Plugins Development Team
7* Original Author : Andreas Ericsson <ae@op5.se> 7 * Original Author : Andreas Ericsson <ae@op5.se>
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_icmp plugin 11 * This file contains the check_icmp plugin
12* 12 *
13* Relevant RFC's: 792 (ICMP), 791 (IP) 13 * Relevant RFC's: 792 (ICMP), 791 (IP)
14* 14 *
15* This program was modeled somewhat after the check_icmp program, 15 * This program was modeled somewhat after the check_icmp program,
16* which was in turn a hack of fping (www.fping.org) but has been 16 * which was in turn a hack of fping (www.fping.org) but has been
17* completely rewritten since to generate higher precision rta values, 17 * completely rewritten since to generate higher precision rta values,
18* and support several different modes as well as setting ttl to control. 18 * and support several different modes as well as setting ttl to control.
19* redundant routes. The only remainders of fping is currently a few 19 * redundant routes. The only remainders of fping is currently a few
20* function names. 20 * function names.
21* 21 *
22* 22 *
23* This program is free software: you can redistribute it and/or modify 23 * This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24 * it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25 * the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26 * (at your option) any later version.
27* 27 *
28* This program is distributed in the hope that it will be useful, 28 * This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31 * GNU General Public License for more details.
32* 32 *
33* You should have received a copy of the GNU General Public License 33 * You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35 *
36* 36 *
37*****************************************************************************/ 37 *****************************************************************************/
38 38
39/* progname may change */ 39/* progname may change */
40/* char *progname = "check_icmp"; */ 40/* char *progname = "check_icmp"; */
41char *progname; 41char *progname;
42const char *copyright = "2005-2008"; 42const char *copyright = "2005-2024";
43const char *email = "devel@monitoring-plugins.org"; 43const char *email = "devel@monitoring-plugins.org";
44 44
45/** Monitoring Plugins basic includes */ 45/** Monitoring Plugins basic includes */
@@ -48,7 +48,7 @@ const char *email = "devel@monitoring-plugins.org";
48#include "utils.h" 48#include "utils.h"
49 49
50#if HAVE_SYS_SOCKIO_H 50#if HAVE_SYS_SOCKIO_H
51#include <sys/sockio.h> 51# include <sys/sockio.h>
52#endif 52#endif
53 53
54#include <sys/time.h> 54#include <sys/time.h>
@@ -64,85 +64,85 @@ const char *email = "devel@monitoring-plugins.org";
64#include <netinet/ip_icmp.h> 64#include <netinet/ip_icmp.h>
65#include <netinet/icmp6.h> 65#include <netinet/icmp6.h>
66#include <arpa/inet.h> 66#include <arpa/inet.h>
67 67#include <math.h>
68 68
69/** sometimes undefined system macros (quite a few, actually) **/ 69/** sometimes undefined system macros (quite a few, actually) **/
70#ifndef MAXTTL 70#ifndef MAXTTL
71# define MAXTTL 255 71# define MAXTTL 255
72#endif 72#endif
73#ifndef INADDR_NONE 73#ifndef INADDR_NONE
74# define INADDR_NONE (in_addr_t)(-1) 74# define INADDR_NONE (in_addr_t)(-1)
75#endif 75#endif
76 76
77#ifndef SOL_IP 77#ifndef SOL_IP
78#define SOL_IP 0 78# define SOL_IP 0
79#endif 79#endif
80 80
81/* we bundle these in one #ifndef, since they're all from BSD 81/* we bundle these in one #ifndef, since they're all from BSD
82 * Put individual #ifndef's around those that bother you */ 82 * Put individual #ifndef's around those that bother you */
83#ifndef ICMP_UNREACH_NET_UNKNOWN 83#ifndef ICMP_UNREACH_NET_UNKNOWN
84# define ICMP_UNREACH_NET_UNKNOWN 6 84# define ICMP_UNREACH_NET_UNKNOWN 6
85# define ICMP_UNREACH_HOST_UNKNOWN 7 85# define ICMP_UNREACH_HOST_UNKNOWN 7
86# define ICMP_UNREACH_ISOLATED 8 86# define ICMP_UNREACH_ISOLATED 8
87# define ICMP_UNREACH_NET_PROHIB 9 87# define ICMP_UNREACH_NET_PROHIB 9
88# define ICMP_UNREACH_HOST_PROHIB 10 88# define ICMP_UNREACH_HOST_PROHIB 10
89# define ICMP_UNREACH_TOSNET 11 89# define ICMP_UNREACH_TOSNET 11
90# define ICMP_UNREACH_TOSHOST 12 90# define ICMP_UNREACH_TOSHOST 12
91#endif 91#endif
92/* tru64 has the ones above, but not these */ 92/* tru64 has the ones above, but not these */
93#ifndef ICMP_UNREACH_FILTER_PROHIB 93#ifndef ICMP_UNREACH_FILTER_PROHIB
94# define ICMP_UNREACH_FILTER_PROHIB 13 94# define ICMP_UNREACH_FILTER_PROHIB 13
95# define ICMP_UNREACH_HOST_PRECEDENCE 14 95# define ICMP_UNREACH_HOST_PRECEDENCE 14
96# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 96# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
97#endif 97#endif
98 98
99typedef unsigned short range_t; /* type for get_range() -- unimplemented */ 99typedef unsigned short range_t; /* type for get_range() -- unimplemented */
100 100
101typedef struct rta_host { 101typedef struct rta_host {
102 unsigned short id; /* id in **table, and icmp pkts */ 102 unsigned short id; /* id in **table, and icmp pkts */
103 char *name; /* arg used for adding this host */ 103 char *name; /* arg used for adding this host */
104 char *msg; /* icmp error message, if any */ 104 char *msg; /* icmp error message, if any */
105 struct sockaddr_storage saddr_in; /* the address of this host */ 105 struct sockaddr_storage saddr_in; /* the address of this host */
106 struct sockaddr_storage error_addr; /* stores address of error replies */ 106 struct sockaddr_storage error_addr; /* stores address of error replies */
107 unsigned long long time_waited; /* total time waited, in usecs */ 107 unsigned long long time_waited; /* total time waited, in usecs */
108 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ 108 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
109 unsigned char icmp_type, icmp_code; /* type and code from errors */ 109 unsigned char icmp_type, icmp_code; /* type and code from errors */
110 unsigned short flags; /* control/status flags */ 110 unsigned short flags; /* control/status flags */
111 double rta; /* measured RTA */ 111 double rta; /* measured RTA */
112 int rta_status; // check result for RTA checks 112 int rta_status; // check result for RTA checks
113 double rtmax; /* max rtt */ 113 double rtmax; /* max rtt */
114 double rtmin; /* min rtt */ 114 double rtmin; /* min rtt */
115 double jitter; /* measured jitter */ 115 double jitter; /* measured jitter */
116 int jitter_status; // check result for Jitter checks 116 int jitter_status; // check result for Jitter checks
117 double jitter_max; /* jitter rtt maximum */ 117 double jitter_max; /* jitter rtt maximum */
118 double jitter_min; /* jitter rtt minimum */ 118 double jitter_min; /* jitter rtt minimum */
119 double EffectiveLatency; 119 double EffectiveLatency;
120 double mos; /* Mean opnion score */ 120 double mos; /* Mean opnion score */
121 int mos_status; // check result for MOS checks 121 int mos_status; // check result for MOS checks
122 double score; /* score */ 122 double score; /* score */
123 int score_status; // check result for score checks 123 int score_status; // check result for score checks
124 u_int last_tdiff; 124 u_int last_tdiff;
125 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */ 125 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
126 unsigned char pl; /* measured packet loss */ 126 unsigned char pl; /* measured packet loss */
127 int pl_status; // check result for packet loss checks 127 int pl_status; // check result for packet loss checks
128 struct rta_host *next; /* linked list */ 128 struct rta_host *next; /* linked list */
129 int order_status; // check result for packet order checks 129 int order_status; // check result for packet order checks
130} rta_host; 130} rta_host;
131 131
132#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ 132#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */
133 133
134/* threshold structure. all values are maximum allowed, exclusive */ 134/* threshold structure. all values are maximum allowed, exclusive */
135typedef struct threshold { 135typedef struct threshold {
136 unsigned char pl; /* max allowed packet loss in percent */ 136 unsigned char pl; /* max allowed packet loss in percent */
137 unsigned int rta; /* roundtrip time average, microseconds */ 137 unsigned int rta; /* roundtrip time average, microseconds */
138 double jitter; /* jitter time average, microseconds */ 138 double jitter; /* jitter time average, microseconds */
139 double mos; /* MOS */ 139 double mos; /* MOS */
140 double score; /* Score */ 140 double score; /* Score */
141} threshold; 141} threshold;
142 142
143/* the data structure */ 143/* the data structure */
144typedef struct icmp_ping_data { 144typedef struct icmp_ping_data {
145 struct timeval stime; /* timestamp (saved in protocol struct as well) */ 145 struct timeval stime; /* timestamp (saved in protocol struct as well) */
146 unsigned short ping_id; 146 unsigned short ping_id;
147} icmp_ping_data; 147} icmp_ping_data;
148 148
@@ -171,10 +171,10 @@ typedef union icmp_packet {
171 * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without 171 * MODE_ICMP: implement something similar to check_icmp (MODE_RTA without
172 * tcp and udp args does this) 172 * tcp and udp args does this)
173 */ 173 */
174#define MODE_RTA 0 174#define MODE_RTA 0
175#define MODE_HOSTCHECK 1 175#define MODE_HOSTCHECK 1
176#define MODE_ALL 2 176#define MODE_ALL 2
177#define MODE_ICMP 3 177#define MODE_ICMP 3
178 178
179enum enum_threshold_mode { 179enum enum_threshold_mode {
180 const_rta_mode, 180 const_rta_mode,
@@ -189,30 +189,30 @@ typedef enum enum_threshold_mode threshold_mode;
189/* the different ping types we can do 189/* the different ping types we can do
190 * TODO: investigate ARP ping as well */ 190 * TODO: investigate ARP ping as well */
191#define HAVE_ICMP 1 191#define HAVE_ICMP 1
192#define HAVE_UDP 2 192#define HAVE_UDP 2
193#define HAVE_TCP 4 193#define HAVE_TCP 4
194#define HAVE_ARP 8 194#define HAVE_ARP 8
195 195
196#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data) 196#define MIN_PING_DATA_SIZE sizeof(struct icmp_ping_data)
197#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */ 197#define MAX_IP_PKT_SIZE 65536 /* (theoretical) max IP packet size */
198#define IP_HDR_SIZE 20 198#define IP_HDR_SIZE 20
199#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN) 199#define MAX_PING_DATA (MAX_IP_PKT_SIZE - IP_HDR_SIZE - ICMP_MINLEN)
200#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44) 200#define DEFAULT_PING_DATA_SIZE (MIN_PING_DATA_SIZE + 44)
201 201
202/* various target states */ 202/* various target states */
203#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */ 203#define TSTATE_INACTIVE 0x01 /* don't ping this host anymore */
204#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */ 204#define TSTATE_WAITING 0x02 /* unanswered packets on the wire */
205#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */ 205#define TSTATE_ALIVE 0x04 /* target is alive (has answered something) */
206#define TSTATE_UNREACH 0x08 206#define TSTATE_UNREACH 0x08
207 207
208/** prototypes **/ 208/** prototypes **/
209void print_help (void); 209void print_help(void);
210void print_usage (void); 210void print_usage(void);
211static u_int get_timevar(const char *); 211static u_int get_timevar(const char *);
212static u_int get_timevaldiff(struct timeval *, struct timeval *); 212static u_int get_timevaldiff(struct timeval *, struct timeval *);
213static in_addr_t get_ip_address(const char *); 213static in_addr_t get_ip_address(const char *);
214static int wait_for_reply(int, u_int); 214static int wait_for_reply(int, u_int);
215static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval*); 215static int recvfrom_wto(int, void *, unsigned int, struct sockaddr *, u_int *, struct timeval *);
216static int send_icmp_ping(int, struct rta_host *); 216static int send_icmp_ping(int, struct rta_host *);
217static int get_threshold(char *str, threshold *th); 217static int get_threshold(char *str, threshold *th);
218static bool get_threshold2(char *str, size_t length, threshold *, threshold *, threshold_mode mode); 218static bool get_threshold2(char *str, size_t length, threshold *, threshold *, threshold_mode mode);
@@ -235,20 +235,8 @@ extern char **environ;
235/** global variables **/ 235/** global variables **/
236static struct rta_host **table, *cursor, *list; 236static struct rta_host **table, *cursor, *list;
237 237
238static threshold crit = { 238static threshold crit = {.pl = 80, .rta = 500000, .jitter = 0.0, .mos = 0.0, .score = 0.0};
239 .pl = 80, 239static threshold warn = {.pl = 40, .rta = 200000, .jitter = 0.0, .mos = 0.0, .score = 0.0};
240 .rta = 500000,
241 .jitter = 0.0,
242 .mos = 0.0,
243 .score = 0.0
244};
245static threshold warn = {
246 .pl = 40,
247 .rta = 200000,
248 .jitter = 0.0,
249 .mos = 0.0,
250 .score = 0.0
251};
252 240
253static int mode, protocols, sockets, debug = 0, timeout = 10; 241static int mode, protocols, sockets, debug = 0, timeout = 10;
254static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; 242static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE;
@@ -266,19 +254,17 @@ static struct timeval prog_start;
266static unsigned long long max_completion_time = 0; 254static unsigned long long max_completion_time = 0;
267static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */ 255static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */
268static int min_hosts_alive = -1; 256static int min_hosts_alive = -1;
269float pkt_backoff_factor = 1.5; 257static float pkt_backoff_factor = 1.5;
270float target_backoff_factor = 1.5; 258static float target_backoff_factor = 1.5;
271bool rta_mode=false; 259static bool rta_mode = false;
272bool pl_mode=false; 260static bool pl_mode = false;
273bool jitter_mode=false; 261static bool jitter_mode = false;
274bool score_mode=false; 262static bool score_mode = false;
275bool mos_mode=false; 263static bool mos_mode = false;
276bool order_mode=false; 264static bool order_mode = false;
277 265
278/** code start **/ 266/** code start **/
279static void 267static void crash(const char *fmt, ...) {
280crash(const char *fmt, ...)
281{
282 va_list ap; 268 va_list ap;
283 269
284 printf("%s: ", progname); 270 printf("%s: ", progname);
@@ -287,55 +273,102 @@ crash(const char *fmt, ...)
287 vprintf(fmt, ap); 273 vprintf(fmt, ap);
288 va_end(ap); 274 va_end(ap);
289 275
290 if(errno) printf(": %s", strerror(errno)); 276 if (errno) {
277 printf(": %s", strerror(errno));
278 }
291 puts(""); 279 puts("");
292 280
293 exit(3); 281 exit(3);
294} 282}
295 283
296 284static const char *get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code) {
297static const char *
298get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
299{
300 const char *msg = "unreachable"; 285 const char *msg = "unreachable";
301 286
302 if(debug > 1) printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code); 287 if (debug > 1) {
303 switch(icmp_type) { 288 printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code);
289 }
290 switch (icmp_type) {
304 case ICMP_UNREACH: 291 case ICMP_UNREACH:
305 switch(icmp_code) { 292 switch (icmp_code) {
306 case ICMP_UNREACH_NET: msg = "Net unreachable"; break; 293 case ICMP_UNREACH_NET:
307 case ICMP_UNREACH_HOST: msg = "Host unreachable"; break; 294 msg = "Net unreachable";
308 case ICMP_UNREACH_PROTOCOL: msg = "Protocol unreachable (firewall?)"; break; 295 break;
309 case ICMP_UNREACH_PORT: msg = "Port unreachable (firewall?)"; break; 296 case ICMP_UNREACH_HOST:
310 case ICMP_UNREACH_NEEDFRAG: msg = "Fragmentation needed"; break; 297 msg = "Host unreachable";
311 case ICMP_UNREACH_SRCFAIL: msg = "Source route failed"; break; 298 break;
312 case ICMP_UNREACH_ISOLATED: msg = "Source host isolated"; break; 299 case ICMP_UNREACH_PROTOCOL:
313 case ICMP_UNREACH_NET_UNKNOWN: msg = "Unknown network"; break; 300 msg = "Protocol unreachable (firewall?)";
314 case ICMP_UNREACH_HOST_UNKNOWN: msg = "Unknown host"; break; 301 break;
315 case ICMP_UNREACH_NET_PROHIB: msg = "Network denied (firewall?)"; break; 302 case ICMP_UNREACH_PORT:
316 case ICMP_UNREACH_HOST_PROHIB: msg = "Host denied (firewall?)"; break; 303 msg = "Port unreachable (firewall?)";
317 case ICMP_UNREACH_TOSNET: msg = "Bad TOS for network (firewall?)"; break; 304 break;
318 case ICMP_UNREACH_TOSHOST: msg = "Bad TOS for host (firewall?)"; break; 305 case ICMP_UNREACH_NEEDFRAG:
319 case ICMP_UNREACH_FILTER_PROHIB: msg = "Prohibited by filter (firewall)"; break; 306 msg = "Fragmentation needed";
320 case ICMP_UNREACH_HOST_PRECEDENCE: msg = "Host precedence violation"; break; 307 break;
321 case ICMP_UNREACH_PRECEDENCE_CUTOFF: msg = "Precedence cutoff"; break; 308 case ICMP_UNREACH_SRCFAIL:
322 default: msg = "Invalid code"; break; 309 msg = "Source route failed";
310 break;
311 case ICMP_UNREACH_ISOLATED:
312 msg = "Source host isolated";
313 break;
314 case ICMP_UNREACH_NET_UNKNOWN:
315 msg = "Unknown network";
316 break;
317 case ICMP_UNREACH_HOST_UNKNOWN:
318 msg = "Unknown host";
319 break;
320 case ICMP_UNREACH_NET_PROHIB:
321 msg = "Network denied (firewall?)";
322 break;
323 case ICMP_UNREACH_HOST_PROHIB:
324 msg = "Host denied (firewall?)";
325 break;
326 case ICMP_UNREACH_TOSNET:
327 msg = "Bad TOS for network (firewall?)";
328 break;
329 case ICMP_UNREACH_TOSHOST:
330 msg = "Bad TOS for host (firewall?)";
331 break;
332 case ICMP_UNREACH_FILTER_PROHIB:
333 msg = "Prohibited by filter (firewall)";
334 break;
335 case ICMP_UNREACH_HOST_PRECEDENCE:
336 msg = "Host precedence violation";
337 break;
338 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
339 msg = "Precedence cutoff";
340 break;
341 default:
342 msg = "Invalid code";
343 break;
323 } 344 }
324 break; 345 break;
325 346
326 case ICMP_TIMXCEED: 347 case ICMP_TIMXCEED:
327 /* really 'out of reach', or non-existent host behind a router serving 348 /* really 'out of reach', or non-existent host behind a router serving
328 * two different subnets */ 349 * two different subnets */
329 switch(icmp_code) { 350 switch (icmp_code) {
330 case ICMP_TIMXCEED_INTRANS: msg = "Time to live exceeded in transit"; break; 351 case ICMP_TIMXCEED_INTRANS:
331 case ICMP_TIMXCEED_REASS: msg = "Fragment reassembly time exceeded"; break; 352 msg = "Time to live exceeded in transit";
332 default: msg = "Invalid code"; break; 353 break;
354 case ICMP_TIMXCEED_REASS:
355 msg = "Fragment reassembly time exceeded";
356 break;
357 default:
358 msg = "Invalid code";
359 break;
333 } 360 }
334 break; 361 break;
335 362
336 case ICMP_SOURCEQUENCH: msg = "Transmitting too fast"; break; 363 case ICMP_SOURCEQUENCH:
337 case ICMP_REDIRECT: msg = "Redirect (change route)"; break; 364 msg = "Transmitting too fast";
338 case ICMP_PARAMPROB: msg = "Bad IP header (required option absent)"; break; 365 break;
366 case ICMP_REDIRECT:
367 msg = "Redirect (change route)";
368 break;
369 case ICMP_PARAMPROB:
370 msg = "Bad IP header (required option absent)";
371 break;
339 372
340 /* the following aren't error messages, so ignore */ 373 /* the following aren't error messages, so ignore */
341 case ICMP_TSTAMP: 374 case ICMP_TSTAMP:
@@ -344,25 +377,27 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
344 case ICMP_IREQREPLY: 377 case ICMP_IREQREPLY:
345 case ICMP_MASKREQ: 378 case ICMP_MASKREQ:
346 case ICMP_MASKREPLY: 379 case ICMP_MASKREPLY:
347 default: msg = ""; break; 380 default:
381 msg = "";
382 break;
348 } 383 }
349 384
350 return msg; 385 return msg;
351} 386}
352 387
353static int 388static int handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr) {
354handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
355{
356 struct icmp p, sent_icmp; 389 struct icmp p, sent_icmp;
357 struct rta_host *host = NULL; 390 struct rta_host *host = NULL;
358 391
359 memcpy(&p, packet, sizeof(p)); 392 memcpy(&p, packet, sizeof(p));
360 if(p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) { 393 if (p.icmp_type == ICMP_ECHO && ntohs(p.icmp_id) == pid) {
361 /* echo request from us to us (pinging localhost) */ 394 /* echo request from us to us (pinging localhost) */
362 return 0; 395 return 0;
363 } 396 }
364 397
365 if(debug) printf("handle_random_icmp(%p, %p)\n", (void *)&p, (void *)addr); 398 if (debug) {
399 printf("handle_random_icmp(%p, %p)\n", (void *)&p, (void *)addr);
400 }
366 401
367 /* only handle a few types, since others can't possibly be replies to 402 /* only handle a few types, since others can't possibly be replies to
368 * us in a sane network (if it is anyway, it will be counted as lost 403 * us in a sane network (if it is anyway, it will be counted as lost
@@ -374,44 +409,41 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
374 * TIMXCEED actually sends a proper icmp response we will have passed 409 * TIMXCEED actually sends a proper icmp response we will have passed
375 * too many hops to have a hope of reaching it later, in which case it 410 * too many hops to have a hope of reaching it later, in which case it
376 * indicates overconfidence in the network, poor routing or both. */ 411 * indicates overconfidence in the network, poor routing or both. */
377 if(p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && 412 if (p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED && p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB) {
378 p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB)
379 {
380 return 0; 413 return 0;
381 } 414 }
382 415
383 /* might be for us. At least it holds the original package (according 416 /* might be for us. At least it holds the original package (according
384 * to RFC 792). If it isn't, just ignore it */ 417 * to RFC 792). If it isn't, just ignore it */
385 memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp)); 418 memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp));
386 if(sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || 419 if (sent_icmp.icmp_type != ICMP_ECHO || ntohs(sent_icmp.icmp_id) != pid || ntohs(sent_icmp.icmp_seq) >= targets * packets) {
387 ntohs(sent_icmp.icmp_seq) >= targets*packets) 420 if (debug) {
388 { 421 printf("Packet is no response to a packet we sent\n");
389 if(debug) printf("Packet is no response to a packet we sent\n"); 422 }
390 return 0; 423 return 0;
391 } 424 }
392 425
393 /* it is indeed a response for us */ 426 /* it is indeed a response for us */
394 host = table[ntohs(sent_icmp.icmp_seq)/packets]; 427 host = table[ntohs(sent_icmp.icmp_seq) / packets];
395 if(debug) { 428 if (debug) {
396 char address[INET6_ADDRSTRLEN]; 429 char address[INET6_ADDRSTRLEN];
397 parse_address(addr, address, sizeof(address)); 430 parse_address(addr, address, sizeof(address));
398 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", 431 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", get_icmp_error_msg(p.icmp_type, p.icmp_code), address, host->name);
399 get_icmp_error_msg(p.icmp_type, p.icmp_code),
400 address, host->name);
401 } 432 }
402 433
403 icmp_lost++; 434 icmp_lost++;
404 host->icmp_lost++; 435 host->icmp_lost++;
405 /* don't spend time on lost hosts any more */ 436 /* don't spend time on lost hosts any more */
406 if(host->flags & FLAG_LOST_CAUSE) return 0; 437 if (host->flags & FLAG_LOST_CAUSE) {
438 return 0;
439 }
407 440
408 /* source quench means we're sending too fast, so increase the 441 /* source quench means we're sending too fast, so increase the
409 * interval and mark this packet lost */ 442 * interval and mark this packet lost */
410 if(p.icmp_type == ICMP_SOURCEQUENCH) { 443 if (p.icmp_type == ICMP_SOURCEQUENCH) {
411 pkt_interval *= pkt_backoff_factor; 444 pkt_interval *= pkt_backoff_factor;
412 target_interval *= target_backoff_factor; 445 target_interval *= target_backoff_factor;
413 } 446 } else {
414 else {
415 targets_down++; 447 targets_down++;
416 host->flags |= FLAG_LOST_CAUSE; 448 host->flags |= FLAG_LOST_CAUSE;
417 } 449 }
@@ -422,21 +454,18 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
422 return 0; 454 return 0;
423} 455}
424 456
425void parse_address(struct sockaddr_storage *addr, char *address, int size) 457void parse_address(struct sockaddr_storage *addr, char *address, int size) {
426{
427 switch (address_family) { 458 switch (address_family) {
428 case AF_INET: 459 case AF_INET:
429 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size); 460 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size);
430 break; 461 break;
431 case AF_INET6: 462 case AF_INET6:
432 inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size); 463 inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size);
433 break; 464 break;
434 } 465 }
435} 466}
436 467
437int 468int main(int argc, char **argv) {
438main(int argc, char **argv)
439{
440 int i; 469 int i;
441 char *ptr; 470 char *ptr;
442 long int arg; 471 long int arg;
@@ -450,10 +479,10 @@ main(int argc, char **argv)
450 int on = 1; 479 int on = 1;
451#endif 480#endif
452 char *source_ip = NULL; 481 char *source_ip = NULL;
453 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64"; 482 char *opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64";
454 setlocale (LC_ALL, ""); 483 setlocale(LC_ALL, "");
455 bindtextdomain (PACKAGE, LOCALEDIR); 484 bindtextdomain(PACKAGE, LOCALEDIR);
456 textdomain (PACKAGE); 485 textdomain(PACKAGE);
457 486
458 /* we only need to be setsuid when we get the sockets, so do 487 /* we only need to be setsuid when we get the sockets, so do
459 * that before pointer magic (esp. on network data) */ 488 * that before pointer magic (esp. on network data) */
@@ -465,8 +494,11 @@ main(int argc, char **argv)
465 /* get calling name the old-fashioned way for portability instead 494 /* get calling name the old-fashioned way for portability instead
466 * of relying on the glibc-ism __progname */ 495 * of relying on the glibc-ism __progname */
467 ptr = strrchr(argv[0], '/'); 496 ptr = strrchr(argv[0], '/');
468 if(ptr) progname = &ptr[1]; 497 if (ptr) {
469 else progname = argv[0]; 498 progname = &ptr[1];
499 } else {
500 progname = argv[0];
501 }
470 502
471 /* now set defaults. Use progname to set them initially (allows for 503 /* now set defaults. Use progname to set them initially (allows for
472 * superfast check_host program when target host is up */ 504 * superfast check_host program when target host is up */
@@ -478,31 +510,29 @@ main(int argc, char **argv)
478 crit.rta = 500000; 510 crit.rta = 500000;
479 crit.pl = 80; 511 crit.pl = 80;
480 crit.jitter = 50; 512 crit.jitter = 50;
481 crit.mos= 3; 513 crit.mos = 3;
482 crit.score=70; 514 crit.score = 70;
483 /* Default warning thresholds */ 515 /* Default warning thresholds */
484 warn.rta = 200000; 516 warn.rta = 200000;
485 warn.pl = 40; 517 warn.pl = 40;
486 warn.jitter = 40; 518 warn.jitter = 40;
487 warn.mos= 3.5; 519 warn.mos = 3.5;
488 warn.score=80; 520 warn.score = 80;
489 521
490 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; 522 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
491 pkt_interval = 80000; /* 80 msec packet interval by default */ 523 pkt_interval = 80000; /* 80 msec packet interval by default */
492 packets = 5; 524 packets = 5;
493 525
494 if(!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) { 526 if (!strcmp(progname, "check_icmp") || !strcmp(progname, "check_ping")) {
495 mode = MODE_ICMP; 527 mode = MODE_ICMP;
496 protocols = HAVE_ICMP; 528 protocols = HAVE_ICMP;
497 } 529 } else if (!strcmp(progname, "check_host")) {
498 else if(!strcmp(progname, "check_host")) {
499 mode = MODE_HOSTCHECK; 530 mode = MODE_HOSTCHECK;
500 pkt_interval = 1000000; 531 pkt_interval = 1000000;
501 packets = 5; 532 packets = 5;
502 crit.rta = warn.rta = 1000000; 533 crit.rta = warn.rta = 1000000;
503 crit.pl = warn.pl = 100; 534 crit.pl = warn.pl = 100;
504 } 535 } else if (!strcmp(progname, "check_rta_multi")) {
505 else if(!strcmp(progname, "check_rta_multi")) {
506 mode = MODE_ALL; 536 mode = MODE_ALL;
507 target_interval = 0; 537 target_interval = 0;
508 pkt_interval = 50000; 538 pkt_interval = 50000;
@@ -510,29 +540,33 @@ main(int argc, char **argv)
510 } 540 }
511 541
512 /* support "--help" and "--version" */ 542 /* support "--help" and "--version" */
513 if(argc == 2) { 543 if (argc == 2) {
514 if(!strcmp(argv[1], "--help")) 544 if (!strcmp(argv[1], "--help")) {
515 strcpy(argv[1], "-h"); 545 strcpy(argv[1], "-h");
516 if(!strcmp(argv[1], "--version")) 546 }
547 if (!strcmp(argv[1], "--version")) {
517 strcpy(argv[1], "-V"); 548 strcpy(argv[1], "-V");
549 }
518 } 550 }
519 551
520 /* Parse protocol arguments first */ 552 /* Parse protocol arguments first */
521 for(i = 1; i < argc; i++) { 553 for (i = 1; i < argc; i++) {
522 while((arg = getopt(argc, argv, opts_str)) != EOF) { 554 while ((arg = getopt(argc, argv, opts_str)) != EOF) {
523 switch(arg) { 555 switch (arg) {
524 case '4': 556 case '4':
525 if (address_family != -1) 557 if (address_family != -1) {
526 crash("Multiple protocol versions not supported"); 558 crash("Multiple protocol versions not supported");
559 }
527 address_family = AF_INET; 560 address_family = AF_INET;
528 break; 561 break;
529 case '6': 562 case '6':
530#ifdef USE_IPV6 563#ifdef USE_IPV6
531 if (address_family != -1) 564 if (address_family != -1) {
532 crash("Multiple protocol versions not supported"); 565 crash("Multiple protocol versions not supported");
566 }
533 address_family = AF_INET6; 567 address_family = AF_INET6;
534#else 568#else
535 usage (_("IPv6 support not available\n")); 569 usage(_("IPv6 support not available\n"));
536#endif 570#endif
537 break; 571 break;
538 } 572 }
@@ -545,22 +579,21 @@ main(int argc, char **argv)
545 unsigned long size; 579 unsigned long size;
546 bool err; 580 bool err;
547 /* parse the arguments */ 581 /* parse the arguments */
548 for(i = 1; i < argc; i++) { 582 for (i = 1; i < argc; i++) {
549 while((arg = getopt(argc, argv, opts_str)) != EOF) { 583 while ((arg = getopt(argc, argv, opts_str)) != EOF) {
550 switch(arg) { 584 switch (arg) {
551 case 'v': 585 case 'v':
552 debug++; 586 debug++;
553 break; 587 break;
554 case 'b': 588 case 'b':
555 size = strtol(optarg,NULL,0); 589 size = strtol(optarg, NULL, 0);
556 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 590 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && size < MAX_PING_DATA) {
557 size < MAX_PING_DATA) {
558 icmp_data_size = size; 591 icmp_data_size = size;
559 icmp_pkt_size = size + ICMP_MINLEN; 592 icmp_pkt_size = size + ICMP_MINLEN;
560 } else 593 } else {
561 usage_va("ICMP data length must be between: %lu and %lu", 594 usage_va("ICMP data length must be between: %lu and %lu", sizeof(struct icmp) + sizeof(struct icmp_ping_data),
562 sizeof(struct icmp) + sizeof(struct icmp_ping_data), 595 MAX_PING_DATA - 1);
563 MAX_PING_DATA - 1); 596 }
564 break; 597 break;
565 case 'i': 598 case 'i':
566 pkt_interval = get_timevar(optarg); 599 pkt_interval = get_timevar(optarg);
@@ -580,7 +613,9 @@ main(int argc, char **argv)
580 break; 613 break;
581 case 't': 614 case 't':
582 timeout = strtoul(optarg, NULL, 0); 615 timeout = strtoul(optarg, NULL, 0);
583 if(!timeout) timeout = 10; 616 if (!timeout) {
617 timeout = 10;
618 }
584 break; 619 break;
585 case 'H': 620 case 'H':
586 add_target(optarg); 621 add_target(optarg);
@@ -593,7 +628,7 @@ main(int argc, char **argv)
593 break; 628 break;
594 case 'd': /* implement later, for cluster checks */ 629 case 'd': /* implement later, for cluster checks */
595 warn_down = (unsigned char)strtoul(optarg, &ptr, 0); 630 warn_down = (unsigned char)strtoul(optarg, &ptr, 0);
596 if(ptr) { 631 if (ptr) {
597 crit_down = (unsigned char)strtoul(ptr + 1, NULL, 0); 632 crit_down = (unsigned char)strtoul(ptr + 1, NULL, 0);
598 } 633 }
599 break; 634 break;
@@ -601,54 +636,54 @@ main(int argc, char **argv)
601 source_ip = optarg; 636 source_ip = optarg;
602 break; 637 break;
603 case 'V': /* version */ 638 case 'V': /* version */
604 print_revision (progname, NP_VERSION); 639 print_revision(progname, NP_VERSION);
605 exit (STATE_UNKNOWN); 640 exit(STATE_UNKNOWN);
606 case 'h': /* help */ 641 case 'h': /* help */
607 print_help (); 642 print_help();
608 exit (STATE_UNKNOWN); 643 exit(STATE_UNKNOWN);
609 break; 644 break;
610 case 'R': /* RTA mode */ 645 case 'R': /* RTA mode */
611 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode); 646 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode);
612 if (!err) { 647 if (!err) {
613 crash("Failed to parse RTA threshold"); 648 crash("Failed to parse RTA threshold");
614 } 649 }
615 650
616 rta_mode=true; 651 rta_mode = true;
617 break; 652 break;
618 case 'P': /* packet loss mode */ 653 case 'P': /* packet loss mode */
619 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode); 654 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode);
620 if (!err) { 655 if (!err) {
621 crash("Failed to parse packet loss threshold"); 656 crash("Failed to parse packet loss threshold");
622 } 657 }
623 658
624 pl_mode=true; 659 pl_mode = true;
625 break; 660 break;
626 case 'J': /* jitter mode */ 661 case 'J': /* jitter mode */
627 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode); 662 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode);
628 if (!err) { 663 if (!err) {
629 crash("Failed to parse jitter threshold"); 664 crash("Failed to parse jitter threshold");
630 } 665 }
631 666
632 jitter_mode=true; 667 jitter_mode = true;
633 break; 668 break;
634 case 'M': /* MOS mode */ 669 case 'M': /* MOS mode */
635 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode); 670 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode);
636 if (!err) { 671 if (!err) {
637 crash("Failed to parse MOS threshold"); 672 crash("Failed to parse MOS threshold");
638 } 673 }
639 674
640 mos_mode=true; 675 mos_mode = true;
641 break; 676 break;
642 case 'S': /* score mode */ 677 case 'S': /* score mode */
643 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode); 678 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode);
644 if (!err) { 679 if (!err) {
645 crash("Failed to parse score threshold"); 680 crash("Failed to parse score threshold");
646 } 681 }
647 682
648 score_mode=true; 683 score_mode = true;
649 break; 684 break;
650 case 'O': /* out of order mode */ 685 case 'O': /* out of order mode */
651 order_mode=true; 686 order_mode = true;
652 break; 687 break;
653 } 688 }
654 } 689 }
@@ -663,37 +698,46 @@ main(int argc, char **argv)
663 /* printf("pid = %u\n", pid); */ 698 /* printf("pid = %u\n", pid); */
664 699
665 /* Parse extra opts if any */ 700 /* Parse extra opts if any */
666 argv=np_extra_opts(&argc, argv, progname); 701 argv = np_extra_opts(&argc, argv, progname);
667 702
668 argv = &argv[optind]; 703 argv = &argv[optind];
669 while(*argv) { 704 while (*argv) {
670 add_target(*argv); 705 add_target(*argv);
671 argv++; 706 argv++;
672 } 707 }
673 708
674 if(!targets) { 709 if (!targets) {
675 errno = 0; 710 errno = 0;
676 crash("No hosts to check"); 711 crash("No hosts to check");
677 } 712 }
678 713
679 // add_target might change address_family 714 // add_target might change address_family
680 switch ( address_family ){ 715 switch (address_family) {
681 case AF_INET: icmp_proto = IPPROTO_ICMP; 716 case AF_INET:
682 break; 717 icmp_proto = IPPROTO_ICMP;
683 case AF_INET6: icmp_proto = IPPROTO_ICMPV6; 718 break;
684 break; 719 case AF_INET6:
685 default: crash("Address family not supported"); 720 icmp_proto = IPPROTO_ICMPV6;
721 break;
722 default:
723 crash("Address family not supported");
686 } 724 }
687 if((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1) 725 if ((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1) {
688 sockets |= HAVE_ICMP; 726 sockets |= HAVE_ICMP;
689 else icmp_sockerrno = errno; 727 } else {
728 icmp_sockerrno = errno;
729 }
690 730
691 if( source_ip ) 731 if (source_ip) {
692 set_source_ip(source_ip); 732 set_source_ip(source_ip);
733 }
693 734
694#ifdef SO_TIMESTAMP 735#ifdef SO_TIMESTAMP
695 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) 736 if (setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on))) {
696 if(debug) printf("Warning: no SO_TIMESTAMP support\n"); 737 if (debug) {
738 printf("Warning: no SO_TIMESTAMP support\n");
739 }
740 }
697#endif // SO_TIMESTAMP 741#endif // SO_TIMESTAMP
698 742
699 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */ 743 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */
@@ -702,8 +746,8 @@ main(int argc, char **argv)
702 return 1; 746 return 1;
703 } 747 }
704 748
705 if(!sockets) { 749 if (!sockets) {
706 if(icmp_sock == -1) { 750 if (icmp_sock == -1) {
707 errno = icmp_sockerrno; 751 errno = icmp_sockerrno;
708 crash("Failed to obtain ICMP socket"); 752 crash("Failed to obtain ICMP socket");
709 return -1; 753 return -1;
@@ -719,13 +763,18 @@ main(int argc, char **argv)
719 /* return -1; */ 763 /* return -1; */
720 /* } */ 764 /* } */
721 } 765 }
722 if(!ttl) ttl = 64; 766 if (!ttl) {
767 ttl = 64;
768 }
723 769
724 if(icmp_sock) { 770 if (icmp_sock) {
725 result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl)); 771 result = setsockopt(icmp_sock, SOL_IP, IP_TTL, &ttl, sizeof(ttl));
726 if(debug) { 772 if (debug) {
727 if(result == -1) printf("setsockopt failed\n"); 773 if (result == -1) {
728 else printf("ttl set to %u\n", ttl); 774 printf("setsockopt failed\n");
775 } else {
776 printf("ttl set to %u\n", ttl);
777 }
729 } 778 }
730 } 779 }
731 780
@@ -733,85 +782,90 @@ main(int argc, char **argv)
733 * (nothing will break if they do), but some anal plugin maintainer 782 * (nothing will break if they do), but some anal plugin maintainer
734 * will probably add some printf() thing here later, so it might be 783 * will probably add some printf() thing here later, so it might be
735 * best to at least show them where to do it. ;) */ 784 * best to at least show them where to do it. ;) */
736 if(warn.pl > crit.pl) warn.pl = crit.pl; 785 if (warn.pl > crit.pl) {
737 if(warn.rta > crit.rta) warn.rta = crit.rta; 786 warn.pl = crit.pl;
738 if(warn_down > crit_down) crit_down = warn_down; 787 }
739 if(warn.jitter > crit.jitter) crit.jitter = warn.jitter; 788 if (warn.rta > crit.rta) {
740 if(warn.mos < crit.mos) warn.mos = crit.mos; 789 warn.rta = crit.rta;
741 if(warn.score < crit.score) warn.score = crit.score; 790 }
791 if (warn_down > crit_down) {
792 crit_down = warn_down;
793 }
794 if (warn.jitter > crit.jitter) {
795 crit.jitter = warn.jitter;
796 }
797 if (warn.mos < crit.mos) {
798 warn.mos = crit.mos;
799 }
800 if (warn.score < crit.score) {
801 warn.score = crit.score;
802 }
742 803
743#ifdef HAVE_SIGACTION 804#ifdef HAVE_SIGACTION
744 sig_action.sa_sigaction = NULL; 805 sig_action.sa_sigaction = NULL;
745 sig_action.sa_handler = finish; 806 sig_action.sa_handler = finish;
746 sigfillset(&sig_action.sa_mask); 807 sigfillset(&sig_action.sa_mask);
747 sig_action.sa_flags = SA_NODEFER|SA_RESTART; 808 sig_action.sa_flags = SA_NODEFER | SA_RESTART;
748 sigaction(SIGINT, &sig_action, NULL); 809 sigaction(SIGINT, &sig_action, NULL);
749 sigaction(SIGHUP, &sig_action, NULL); 810 sigaction(SIGHUP, &sig_action, NULL);
750 sigaction(SIGTERM, &sig_action, NULL); 811 sigaction(SIGTERM, &sig_action, NULL);
751 sigaction(SIGALRM, &sig_action, NULL); 812 sigaction(SIGALRM, &sig_action, NULL);
752#else /* HAVE_SIGACTION */ 813#else /* HAVE_SIGACTION */
753 signal(SIGINT, finish); 814 signal(SIGINT, finish);
754 signal(SIGHUP, finish); 815 signal(SIGHUP, finish);
755 signal(SIGTERM, finish); 816 signal(SIGTERM, finish);
756 signal(SIGALRM, finish); 817 signal(SIGALRM, finish);
757#endif /* HAVE_SIGACTION */ 818#endif /* HAVE_SIGACTION */
758 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); 819 if (debug) {
820 printf("Setting alarm timeout to %u seconds\n", timeout);
821 }
759 alarm(timeout); 822 alarm(timeout);
760 823
761 /* make sure we don't wait any longer than necessary */ 824 /* make sure we don't wait any longer than necessary */
762 gettimeofday(&prog_start, &tz); 825 gettimeofday(&prog_start, &tz);
763 max_completion_time = 826 max_completion_time = ((targets * packets * pkt_interval) + (targets * target_interval)) + (targets * packets * crit.rta) + crit.rta;
764 ((targets * packets * pkt_interval) + (targets * target_interval)) +
765 (targets * packets * crit.rta) + crit.rta;
766 827
767 if(debug) { 828 if (debug) {
768 printf("packets: %u, targets: %u\n" 829 printf("packets: %u, targets: %u\n"
769 "target_interval: %0.3f, pkt_interval %0.3f\n" 830 "target_interval: %0.3f, pkt_interval %0.3f\n"
770 "crit.rta: %0.3f\n" 831 "crit.rta: %0.3f\n"
771 "max_completion_time: %0.3f\n", 832 "max_completion_time: %0.3f\n",
772 packets, targets, 833 packets, targets, (float)target_interval / 1000, (float)pkt_interval / 1000, (float)crit.rta / 1000,
773 (float)target_interval / 1000, (float)pkt_interval / 1000,
774 (float)crit.rta / 1000,
775 (float)max_completion_time / 1000); 834 (float)max_completion_time / 1000);
776 } 835 }
777 836
778 if(debug) { 837 if (debug) {
779 if(max_completion_time > (u_int)timeout * 1000000) { 838 if (max_completion_time > (u_int)timeout * 1000000) {
780 printf("max_completion_time: %llu timeout: %u\n", 839 printf("max_completion_time: %llu timeout: %u\n", max_completion_time, timeout);
781 max_completion_time, timeout); 840 printf("Timeout must be at least %llu\n", max_completion_time / 1000000 + 1);
782 printf("Timeout must be at least %llu\n",
783 max_completion_time / 1000000 + 1);
784 } 841 }
785 } 842 }
786 843
787 if(debug) { 844 if (debug) {
788 printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", 845 printf("crit = {%u, %u%%}, warn = {%u, %u%%}\n", crit.rta, crit.pl, warn.rta, warn.pl);
789 crit.rta, crit.pl, warn.rta, warn.pl); 846 printf("pkt_interval: %u target_interval: %u retry_interval: %u\n", pkt_interval, target_interval, retry_interval);
790 printf("pkt_interval: %u target_interval: %u retry_interval: %u\n", 847 printf("icmp_pkt_size: %u timeout: %u\n", icmp_pkt_size, timeout);
791 pkt_interval, target_interval, retry_interval);
792 printf("icmp_pkt_size: %u timeout: %u\n",
793 icmp_pkt_size, timeout);
794 } 848 }
795 849
796 if(packets > 20) { 850 if (packets > 20) {
797 errno = 0; 851 errno = 0;
798 crash("packets is > 20 (%d)", packets); 852 crash("packets is > 20 (%d)", packets);
799 } 853 }
800 854
801 if(min_hosts_alive < -1) { 855 if (min_hosts_alive < -1) {
802 errno = 0; 856 errno = 0;
803 crash("minimum alive hosts is negative (%i)", min_hosts_alive); 857 crash("minimum alive hosts is negative (%i)", min_hosts_alive);
804 } 858 }
805 859
806 host = list; 860 host = list;
807 table = malloc(sizeof(struct rta_host *) * targets); 861 table = malloc(sizeof(struct rta_host *) * targets);
808 if(!table) { 862 if (!table) {
809 crash("main(): malloc failed for host table"); 863 crash("main(): malloc failed for host table");
810 } 864 }
811 865
812 i = 0; 866 i = 0;
813 while(host) { 867 while (host) {
814 host->id = i*packets; 868 host->id = i * packets;
815 table[i] = host; 869 table[i] = host;
816 host = host->next; 870 host = host->next;
817 i++; 871 i++;
@@ -822,25 +876,26 @@ main(int argc, char **argv)
822 errno = 0; 876 errno = 0;
823 finish(0); 877 finish(0);
824 878
825 return(0); 879 return (0);
826} 880}
827 881
828static void 882static void run_checks(void) {
829run_checks()
830{
831 u_int i, t; 883 u_int i, t;
832 u_int final_wait, time_passed; 884 u_int final_wait, time_passed;
833 885
834 /* this loop might actually violate the pkt_interval or target_interval 886 /* this loop might actually violate the pkt_interval or target_interval
835 * settings, but only if there aren't any packets on the wire which 887 * settings, but only if there aren't any packets on the wire which
836 * indicates that the target can handle an increased packet rate */ 888 * indicates that the target can handle an increased packet rate */
837 for(i = 0; i < packets; i++) { 889 for (i = 0; i < packets; i++) {
838 for(t = 0; t < targets; t++) { 890 for (t = 0; t < targets; t++) {
839 /* don't send useless packets */ 891 /* don't send useless packets */
840 if(!targets_alive) finish(0); 892 if (!targets_alive) {
841 if(table[t]->flags & FLAG_LOST_CAUSE) { 893 finish(0);
842 if(debug) printf("%s is a lost cause. not sending any more\n", 894 }
843 table[t]->name); 895 if (table[t]->flags & FLAG_LOST_CAUSE) {
896 if (debug) {
897 printf("%s is a lost cause. not sending any more\n", table[t]->name);
898 }
844 continue; 899 continue;
845 } 900 }
846 901
@@ -851,28 +906,29 @@ run_checks()
851 wait_for_reply(icmp_sock, pkt_interval * targets); 906 wait_for_reply(icmp_sock, pkt_interval * targets);
852 } 907 }
853 908
854 if(icmp_pkts_en_route && targets_alive) { 909 if (icmp_pkts_en_route && targets_alive) {
855 time_passed = get_timevaldiff(NULL, NULL); 910 time_passed = get_timevaldiff(NULL, NULL);
856 final_wait = max_completion_time - time_passed; 911 final_wait = max_completion_time - time_passed;
857 912
858 if(debug) { 913 if (debug) {
859 printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", 914 printf("time_passed: %u final_wait: %u max_completion_time: %llu\n", time_passed, final_wait, max_completion_time);
860 time_passed, final_wait, max_completion_time);
861 } 915 }
862 if(time_passed > max_completion_time) { 916 if (time_passed > max_completion_time) {
863 if(debug) printf("Time passed. Finishing up\n"); 917 if (debug) {
918 printf("Time passed. Finishing up\n");
919 }
864 finish(0); 920 finish(0);
865 } 921 }
866 922
867 /* catch the packets that might come in within the timeframe, but 923 /* catch the packets that might come in within the timeframe, but
868 * haven't yet */ 924 * haven't yet */
869 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", 925 if (debug) {
870 final_wait, (float)final_wait / 1000); 926 printf("Waiting for %u micro-seconds (%0.3f msecs)\n", final_wait, (float)final_wait / 1000);
927 }
871 wait_for_reply(icmp_sock, final_wait); 928 wait_for_reply(icmp_sock, final_wait);
872 } 929 }
873} 930}
874 931
875
876/* response structure: 932/* response structure:
877 * IPv4: 933 * IPv4:
878 * ip header : 20 bytes 934 * ip header : 20 bytes
@@ -883,9 +939,7 @@ run_checks()
883 * both: 939 * both:
884 * icmp echo reply : the rest 940 * icmp echo reply : the rest
885 */ 941 */
886static int 942static int wait_for_reply(int sock, u_int t) {
887wait_for_reply(int sock, u_int t)
888{
889 int n, hlen; 943 int n, hlen;
890 static unsigned char buf[65536]; 944 static unsigned char buf[65536];
891 struct sockaddr_storage resp_addr; 945 struct sockaddr_storage resp_addr;
@@ -898,15 +952,14 @@ wait_for_reply(int sock, u_int t)
898 double jitter_tmp; 952 double jitter_tmp;
899 953
900 if (!(packet.buf = malloc(icmp_pkt_size))) { 954 if (!(packet.buf = malloc(icmp_pkt_size))) {
901 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 955 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
902 icmp_pkt_size); 956 return -1; /* might be reached if we're in debug mode */
903 return -1; /* might be reached if we're in debug mode */
904 } 957 }
905 958
906 memset(packet.buf, 0, icmp_pkt_size); 959 memset(packet.buf, 0, icmp_pkt_size);
907 960
908 /* if we can't listen or don't have anything to listen to, just return */ 961 /* if we can't listen or don't have anything to listen to, just return */
909 if(!t || !icmp_pkts_en_route) { 962 if (!t || !icmp_pkts_en_route) {
910 free(packet.buf); 963 free(packet.buf);
911 return 0; 964 return 0;
912 } 965 }
@@ -915,29 +968,26 @@ wait_for_reply(int sock, u_int t)
915 968
916 i = t; 969 i = t;
917 per_pkt_wait = t / icmp_pkts_en_route; 970 per_pkt_wait = t / icmp_pkts_en_route;
918 while(icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) { 971 while (icmp_pkts_en_route && get_timevaldiff(&wait_start, NULL) < i) {
919 t = per_pkt_wait; 972 t = per_pkt_wait;
920 973
921 /* wrap up if all targets are declared dead */ 974 /* wrap up if all targets are declared dead */
922 if(!targets_alive || 975 if (!targets_alive || get_timevaldiff(&prog_start, NULL) >= max_completion_time || (mode == MODE_HOSTCHECK && targets_down)) {
923 get_timevaldiff(&prog_start, NULL) >= max_completion_time ||
924 (mode == MODE_HOSTCHECK && targets_down))
925 {
926 finish(0); 976 finish(0);
927 } 977 }
928 978
929 /* reap responses until we hit a timeout */ 979 /* reap responses until we hit a timeout */
930 n = recvfrom_wto(sock, buf, sizeof(buf), 980 n = recvfrom_wto(sock, buf, sizeof(buf), (struct sockaddr *)&resp_addr, &t, &now);
931 (struct sockaddr *)&resp_addr, &t, &now); 981 if (!n) {
932 if(!n) { 982 if (debug > 1) {
933 if(debug > 1) { 983 printf("recvfrom_wto() timed out during a %u usecs wait\n", per_pkt_wait);
934 printf("recvfrom_wto() timed out during a %u usecs wait\n",
935 per_pkt_wait);
936 } 984 }
937 continue; /* timeout for this one, so keep trying */ 985 continue; /* timeout for this one, so keep trying */
938 } 986 }
939 if(n < 0) { 987 if (n < 0) {
940 if(debug) printf("recvfrom_wto() returned errors\n"); 988 if (debug) {
989 printf("recvfrom_wto() returned errors\n");
990 }
941 free(packet.buf); 991 free(packet.buf);
942 return n; 992 return n;
943 } 993 }
@@ -946,31 +996,27 @@ wait_for_reply(int sock, u_int t)
946 if (address_family != AF_INET6) { 996 if (address_family != AF_INET6) {
947 ip = (union ip_hdr *)buf; 997 ip = (union ip_hdr *)buf;
948 998
949 if(debug > 1) { 999 if (debug > 1) {
950 char address[INET6_ADDRSTRLEN]; 1000 char address[INET6_ADDRSTRLEN];
951 parse_address(&resp_addr, address, sizeof(address)); 1001 parse_address(&resp_addr, address, sizeof(address));
952 printf("received %u bytes from %s\n", 1002 printf("received %u bytes from %s\n", address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen) : ntohs(ip->ip.ip_len), address);
953 address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen)
954 : ntohs(ip->ip.ip_len),
955 address);
956 } 1003 }
957 } 1004 }
958 1005
959/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ 1006 /* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */
960/* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ 1007 /* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */
961 /* alpha headers are decidedly broken. Using an ansi compiler, 1008 /* alpha headers are decidedly broken. Using an ansi compiler,
962 * they provide ip_vhl instead of ip_hl and ip_v, so we mask 1009 * they provide ip_vhl instead of ip_hl and ip_v, so we mask
963 * off the bottom 4 bits */ 1010 * off the bottom 4 bits */
964/* hlen = (ip->ip_vhl & 0x0f) << 2; */ 1011 /* hlen = (ip->ip_vhl & 0x0f) << 2; */
965/* #else */ 1012 /* #else */
966 hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2; 1013 hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2;
967/* #endif */ 1014 /* #endif */
968 1015
969 if(n < (hlen + ICMP_MINLEN)) { 1016 if (n < (hlen + ICMP_MINLEN)) {
970 char address[INET6_ADDRSTRLEN]; 1017 char address[INET6_ADDRSTRLEN];
971 parse_address(&resp_addr, address, sizeof(address)); 1018 parse_address(&resp_addr, address, sizeof(address));
972 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", 1019 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", n, hlen + icmp_pkt_size, address);
973 n, hlen + icmp_pkt_size, address);
974 } 1020 }
975 /* else if(debug) { */ 1021 /* else if(debug) { */
976 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ 1022 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */
@@ -981,16 +1027,16 @@ wait_for_reply(int sock, u_int t)
981 /* check the response */ 1027 /* check the response */
982 1028
983 memcpy(packet.buf, buf + hlen, icmp_pkt_size); 1029 memcpy(packet.buf, buf + hlen, icmp_pkt_size);
984/* address_family == AF_INET6 ? sizeof(struct icmp6_hdr) 1030 /* address_family == AF_INET6 ? sizeof(struct icmp6_hdr)
985 : sizeof(struct icmp));*/ 1031 : sizeof(struct icmp));*/
986 1032
987 if( (address_family == PF_INET && 1033 if ((address_family == PF_INET && (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY ||
988 (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY 1034 ntohs(packet.icp->icmp_seq) >= targets * packets)) ||
989 || ntohs(packet.icp->icmp_seq) >= targets * packets)) 1035 (address_family == PF_INET6 && (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY ||
990 || (address_family == PF_INET6 && 1036 ntohs(packet.icp6->icmp6_seq) >= targets * packets))) {
991 (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY 1037 if (debug > 2) {
992 || ntohs(packet.icp6->icmp6_seq) >= targets * packets))) { 1038 printf("not a proper ICMP_ECHOREPLY\n");
993 if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n"); 1039 }
994 handle_random_icmp(buf + hlen, &resp_addr); 1040 handle_random_icmp(buf + hlen, &resp_addr);
995 continue; 1041 continue;
996 } 1042 }
@@ -998,23 +1044,23 @@ wait_for_reply(int sock, u_int t)
998 /* this is indeed a valid response */ 1044 /* this is indeed a valid response */
999 if (address_family == PF_INET) { 1045 if (address_family == PF_INET) {
1000 memcpy(&data, packet.icp->icmp_data, sizeof(data)); 1046 memcpy(&data, packet.icp->icmp_data, sizeof(data));
1001 if (debug > 2) 1047 if (debug > 2) {
1002 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", 1048 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id),
1003 (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), 1049 ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum);
1004 ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum); 1050 }
1005 host = table[ntohs(packet.icp->icmp_seq)/packets]; 1051 host = table[ntohs(packet.icp->icmp_seq) / packets];
1006 } else { 1052 } else {
1007 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data)); 1053 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data));
1008 if (debug > 2) 1054 if (debug > 2) {
1009 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", 1055 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id),
1010 (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id), 1056 ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum);
1011 ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum); 1057 }
1012 host = table[ntohs(packet.icp6->icmp6_seq)/packets]; 1058 host = table[ntohs(packet.icp6->icmp6_seq) / packets];
1013 } 1059 }
1014 1060
1015 tdiff = get_timevaldiff(&data.stime, &now); 1061 tdiff = get_timevaldiff(&data.stime, &now);
1016 1062
1017 if (host->last_tdiff>0) { 1063 if (host->last_tdiff > 0) {
1018 /* Calculate jitter */ 1064 /* Calculate jitter */
1019 if (host->last_tdiff > tdiff) { 1065 if (host->last_tdiff > tdiff) {
1020 jitter_tmp = host->last_tdiff - tdiff; 1066 jitter_tmp = host->last_tdiff - tdiff;
@@ -1022,71 +1068,66 @@ wait_for_reply(int sock, u_int t)
1022 jitter_tmp = tdiff - host->last_tdiff; 1068 jitter_tmp = tdiff - host->last_tdiff;
1023 } 1069 }
1024 1070
1025 if (host->jitter==0) { 1071 if (host->jitter == 0) {
1026 host->jitter=jitter_tmp; 1072 host->jitter = jitter_tmp;
1027 host->jitter_max=jitter_tmp; 1073 host->jitter_max = jitter_tmp;
1028 host->jitter_min=jitter_tmp; 1074 host->jitter_min = jitter_tmp;
1029 } else { 1075 } else {
1030 host->jitter+=jitter_tmp; 1076 host->jitter += jitter_tmp;
1031 1077
1032 if (jitter_tmp < host->jitter_min) { 1078 if (jitter_tmp < host->jitter_min) {
1033 host->jitter_min=jitter_tmp; 1079 host->jitter_min = jitter_tmp;
1034 } 1080 }
1035 1081
1036 if (jitter_tmp > host->jitter_max) { 1082 if (jitter_tmp > host->jitter_max) {
1037 host->jitter_max=jitter_tmp; 1083 host->jitter_max = jitter_tmp;
1038 } 1084 }
1039 } 1085 }
1040 1086
1041 /* Check if packets in order */ 1087 /* Check if packets in order */
1042 if (host->last_icmp_seq >= packet.icp->icmp_seq) 1088 if (host->last_icmp_seq >= packet.icp->icmp_seq) {
1043 host->order_status=STATE_CRITICAL; 1089 host->order_status = STATE_CRITICAL;
1090 }
1044 } 1091 }
1045 host->last_tdiff=tdiff; 1092 host->last_tdiff = tdiff;
1046 1093
1047 host->last_icmp_seq=packet.icp->icmp_seq; 1094 host->last_icmp_seq = packet.icp->icmp_seq;
1048 1095
1049 host->time_waited += tdiff; 1096 host->time_waited += tdiff;
1050 host->icmp_recv++; 1097 host->icmp_recv++;
1051 icmp_recv++; 1098 icmp_recv++;
1052 if (tdiff > (unsigned int)host->rtmax) 1099
1100 if (tdiff > (unsigned int)host->rtmax) {
1053 host->rtmax = tdiff; 1101 host->rtmax = tdiff;
1054 if (tdiff < (unsigned int)host->rtmin) 1102 }
1103
1104 if ((host->rtmin == INFINITY) || (tdiff < (unsigned int)host->rtmin)) {
1055 host->rtmin = tdiff; 1105 host->rtmin = tdiff;
1106 }
1056 1107
1057 if(debug) { 1108 if (debug) {
1058 char address[INET6_ADDRSTRLEN]; 1109 char address[INET6_ADDRSTRLEN];
1059 parse_address(&resp_addr, address, sizeof(address)); 1110 parse_address(&resp_addr, address, sizeof(address));
1060 1111
1061 switch(address_family) { 1112 switch (address_family) {
1062 case AF_INET: { 1113 case AF_INET: {
1063 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 1114 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address,
1064 (float)tdiff / 1000, 1115 ttl, ip->ip.ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000);
1065 address, 1116 break;
1066 ttl, 1117 };
1067 ip->ip.ip_ttl, 1118 case AF_INET6: {
1068 (float)host->rtmax / 1000, 1119 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n", (float)tdiff / 1000, address, ttl,
1069 (float)host->rtmin / 1000); 1120 (float)host->rtmax / 1000, (float)host->rtmin / 1000);
1070 break; 1121 };
1071 }; 1122 }
1072 case AF_INET6: {
1073 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n",
1074 (float)tdiff / 1000,
1075 address,
1076 ttl,
1077 (float)host->rtmax / 1000,
1078 (float)host->rtmin / 1000);
1079 };
1080 }
1081 } 1123 }
1082 1124
1083 /* if we're in hostcheck mode, exit with limited printouts */ 1125 /* if we're in hostcheck mode, exit with limited printouts */
1084 if(mode == MODE_HOSTCHECK) { 1126 if (mode == MODE_HOSTCHECK) {
1085 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|" 1127 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
1086 "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", 1128 "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
1087 host->name, icmp_recv, (float)tdiff / 1000, 1129 host->name, icmp_recv, (float)tdiff / 1000, icmp_recv, packets, (float)tdiff / 1000, (float)warn.rta / 1000,
1088 icmp_recv, packets, (float)tdiff / 1000, 1130 (float)crit.rta / 1000);
1089 (float)warn.rta / 1000, (float)crit.rta / 1000);
1090 exit(STATE_OK); 1131 exit(STATE_OK);
1091 } 1132 }
1092 } 1133 }
@@ -1096,9 +1137,7 @@ wait_for_reply(int sock, u_int t)
1096} 1137}
1097 1138
1098/* the ping functions */ 1139/* the ping functions */
1099static int 1140static int send_icmp_ping(int sock, struct rta_host *host) {
1100send_icmp_ping(int sock, struct rta_host *host)
1101{
1102 long int len; 1141 long int len;
1103 size_t addrlen; 1142 size_t addrlen;
1104 struct icmp_ping_data data; 1143 struct icmp_ping_data data;
@@ -1107,22 +1146,21 @@ send_icmp_ping(int sock, struct rta_host *host)
1107 struct timeval tv; 1146 struct timeval tv;
1108 void *buf = NULL; 1147 void *buf = NULL;
1109 1148
1110 if(sock == -1) { 1149 if (sock == -1) {
1111 errno = 0; 1150 errno = 0;
1112 crash("Attempt to send on bogus socket"); 1151 crash("Attempt to send on bogus socket");
1113 return -1; 1152 return -1;
1114 } 1153 }
1115 1154
1116 if(!buf) { 1155 if (!buf) {
1117 if (!(buf = malloc(icmp_pkt_size))) { 1156 if (!(buf = malloc(icmp_pkt_size))) {
1118 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 1157 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", icmp_pkt_size);
1119 icmp_pkt_size); 1158 return -1; /* might be reached if we're in debug mode */
1120 return -1; /* might be reached if we're in debug mode */
1121 } 1159 }
1122 } 1160 }
1123 memset(buf, 0, icmp_pkt_size); 1161 memset(buf, 0, icmp_pkt_size);
1124 1162
1125 if((gettimeofday(&tv, &tz)) == -1) { 1163 if ((gettimeofday(&tv, &tz)) == -1) {
1126 free(buf); 1164 free(buf);
1127 return -1; 1165 return -1;
1128 } 1166 }
@@ -1131,7 +1169,7 @@ send_icmp_ping(int sock, struct rta_host *host)
1131 memcpy(&data.stime, &tv, sizeof(tv)); 1169 memcpy(&data.stime, &tv, sizeof(tv));
1132 1170
1133 if (address_family == AF_INET) { 1171 if (address_family == AF_INET) {
1134 struct icmp *icp = (struct icmp*)buf; 1172 struct icmp *icp = (struct icmp *)buf;
1135 addrlen = sizeof(struct sockaddr_in); 1173 addrlen = sizeof(struct sockaddr_in);
1136 1174
1137 memcpy(&icp->icmp_data, &data, sizeof(data)); 1175 memcpy(&icp->icmp_data, &data, sizeof(data));
@@ -1141,14 +1179,14 @@ send_icmp_ping(int sock, struct rta_host *host)
1141 icp->icmp_cksum = 0; 1179 icp->icmp_cksum = 0;
1142 icp->icmp_id = htons(pid); 1180 icp->icmp_id = htons(pid);
1143 icp->icmp_seq = htons(host->id++); 1181 icp->icmp_seq = htons(host->id++);
1144 icp->icmp_cksum = icmp_checksum((uint16_t*)buf, (size_t)icmp_pkt_size); 1182 icp->icmp_cksum = icmp_checksum((uint16_t *)buf, (size_t)icmp_pkt_size);
1145 1183
1146 if (debug > 2) 1184 if (debug > 2) {
1147 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 1185 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", (unsigned long)sizeof(data),
1148 (unsigned long)sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name); 1186 ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name);
1149 } 1187 }
1150 else { 1188 } else {
1151 struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf; 1189 struct icmp6_hdr *icp6 = (struct icmp6_hdr *)buf;
1152 addrlen = sizeof(struct sockaddr_in6); 1190 addrlen = sizeof(struct sockaddr_in6);
1153 1191
1154 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data)); 1192 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data));
@@ -1161,9 +1199,8 @@ send_icmp_ping(int sock, struct rta_host *host)
1161 // let checksum be calculated automatically 1199 // let checksum be calculated automatically
1162 1200
1163 if (debug > 2) { 1201 if (debug > 2) {
1164 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 1202 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", (unsigned long)sizeof(data),
1165 (unsigned long)sizeof(data), ntohs(icp6->icmp6_id), 1203 ntohs(icp6->icmp6_id), ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name);
1166 ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name);
1167 } 1204 }
1168 } 1205 }
1169 1206
@@ -1188,8 +1225,8 @@ send_icmp_ping(int sock, struct rta_host *host)
1188 1225
1189 free(buf); 1226 free(buf);
1190 1227
1191 if(len < 0 || (unsigned int)len != icmp_pkt_size) { 1228 if (len < 0 || (unsigned int)len != icmp_pkt_size) {
1192 if(debug) { 1229 if (debug) {
1193 char address[INET6_ADDRSTRLEN]; 1230 char address[INET6_ADDRSTRLEN];
1194 parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address)); 1231 parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address));
1195 printf("Failed to send ping to %s: %s\n", address, strerror(errno)); 1232 printf("Failed to send ping to %s: %s\n", address, strerror(errno));
@@ -1204,10 +1241,7 @@ send_icmp_ping(int sock, struct rta_host *host)
1204 return 0; 1241 return 0;
1205} 1242}
1206 1243
1207static int 1244static int recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr, u_int *timo, struct timeval *tv) {
1208recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1209 u_int *timo, struct timeval* tv)
1210{
1211 u_int slen; 1245 u_int slen;
1212 int n, ret; 1246 int n, ret;
1213 struct timeval to, then, now; 1247 struct timeval to, then, now;
@@ -1218,11 +1252,13 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1218 struct msghdr hdr; 1252 struct msghdr hdr;
1219 struct iovec iov; 1253 struct iovec iov;
1220#ifdef SO_TIMESTAMP 1254#ifdef SO_TIMESTAMP
1221 struct cmsghdr* chdr; 1255 struct cmsghdr *chdr;
1222#endif 1256#endif
1223 1257
1224 if(!*timo) { 1258 if (!*timo) {
1225 if(debug) printf("*timo is not\n"); 1259 if (debug) {
1260 printf("*timo is not\n");
1261 }
1226 return 0; 1262 return 0;
1227 } 1263 }
1228 1264
@@ -1235,11 +1271,15 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1235 errno = 0; 1271 errno = 0;
1236 gettimeofday(&then, &tz); 1272 gettimeofday(&then, &tz);
1237 n = select(sock + 1, &rd, &wr, NULL, &to); 1273 n = select(sock + 1, &rd, &wr, NULL, &to);
1238 if(n < 0) crash("select() in recvfrom_wto"); 1274 if (n < 0) {
1275 crash("select() in recvfrom_wto");
1276 }
1239 gettimeofday(&now, &tz); 1277 gettimeofday(&now, &tz);
1240 *timo = get_timevaldiff(&then, &now); 1278 *timo = get_timevaldiff(&then, &now);
1241 1279
1242 if(!n) return 0; /* timeout */ 1280 if (!n) {
1281 return 0; /* timeout */
1282 }
1243 1283
1244 slen = sizeof(struct sockaddr_storage); 1284 slen = sizeof(struct sockaddr_storage);
1245 1285
@@ -1259,12 +1299,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1259 1299
1260 ret = recvmsg(sock, &hdr, 0); 1300 ret = recvmsg(sock, &hdr, 0);
1261#ifdef SO_TIMESTAMP 1301#ifdef SO_TIMESTAMP
1262 for(chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) { 1302 for (chdr = CMSG_FIRSTHDR(&hdr); chdr; chdr = CMSG_NXTHDR(&hdr, chdr)) {
1263 if(chdr->cmsg_level == SOL_SOCKET 1303 if (chdr->cmsg_level == SOL_SOCKET && chdr->cmsg_type == SO_TIMESTAMP && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
1264 && chdr->cmsg_type == SO_TIMESTAMP
1265 && chdr->cmsg_len >= CMSG_LEN(sizeof(struct timeval))) {
1266 memcpy(tv, CMSG_DATA(chdr), sizeof(*tv)); 1304 memcpy(tv, CMSG_DATA(chdr), sizeof(*tv));
1267 break ; 1305 break;
1268 } 1306 }
1269 } 1307 }
1270 1308
@@ -1274,54 +1312,60 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1274 return (ret); 1312 return (ret);
1275} 1313}
1276 1314
1277static void 1315static void finish(int sig) {
1278finish(int sig)
1279{
1280 u_int i = 0; 1316 u_int i = 0;
1281 unsigned char pl; 1317 unsigned char pl;
1282 double rta; 1318 double rta;
1283 struct rta_host *host; 1319 struct rta_host *host;
1284 const char *status_string[] = 1320 const char *status_string[] = {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1285 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1286 int hosts_ok = 0; 1321 int hosts_ok = 0;
1287 int hosts_warn = 0; 1322 int hosts_warn = 0;
1288 int this_status; 1323 int this_status;
1289 double R; 1324 double R;
1290 1325
1291 alarm(0); 1326 alarm(0);
1292 if(debug > 1) printf("finish(%d) called\n", sig); 1327 if (debug > 1) {
1328 printf("finish(%d) called\n", sig);
1329 }
1293 1330
1294 if(icmp_sock != -1) close(icmp_sock); 1331 if (icmp_sock != -1) {
1295 if(udp_sock != -1) close(udp_sock); 1332 close(icmp_sock);
1296 if(tcp_sock != -1) close(tcp_sock); 1333 }
1334 if (udp_sock != -1) {
1335 close(udp_sock);
1336 }
1337 if (tcp_sock != -1) {
1338 close(tcp_sock);
1339 }
1297 1340
1298 if(debug) { 1341 if (debug) {
1299 printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", 1342 printf("icmp_sent: %u icmp_recv: %u icmp_lost: %u\n", icmp_sent, icmp_recv, icmp_lost);
1300 icmp_sent, icmp_recv, icmp_lost);
1301 printf("targets: %u targets_alive: %u\n", targets, targets_alive); 1343 printf("targets: %u targets_alive: %u\n", targets, targets_alive);
1302 } 1344 }
1303 1345
1304 /* iterate thrice to calculate values, give output, and print perfparse */ 1346 /* iterate thrice to calculate values, give output, and print perfparse */
1305 status=STATE_OK; 1347 status = STATE_OK;
1306 host = list; 1348 host = list;
1307 1349
1308 while(host) { 1350 while (host) {
1309 this_status = STATE_OK; 1351 this_status = STATE_OK;
1310 1352
1311 if(!host->icmp_recv) { 1353 if (!host->icmp_recv) {
1312 /* rta 0 is ofcourse not entirely correct, but will still show up 1354 /* rta 0 is ofcourse not entirely correct, but will still show up
1313 * conspicuously as missing entries in perfparse and cacti */ 1355 * conspicuously as missing entries in perfparse and cacti */
1314 pl = 100; 1356 pl = 100;
1315 rta = 0; 1357 rta = 0;
1316 status = STATE_CRITICAL; 1358 status = STATE_CRITICAL;
1317 /* up the down counter if not already counted */ 1359 /* up the down counter if not already counted */
1318 if(!(host->flags & FLAG_LOST_CAUSE) && targets_alive) targets_down++; 1360 if (!(host->flags & FLAG_LOST_CAUSE) && targets_alive) {
1361 targets_down++;
1362 }
1319 } else { 1363 } else {
1320 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1364 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1321 rta = (double)host->time_waited / host->icmp_recv; 1365 rta = (double)host->time_waited / host->icmp_recv;
1322 } 1366 }
1323 1367
1324 if (host->icmp_recv>1) { 1368 if (host->icmp_recv > 1) {
1325 /* 1369 /*
1326 * This algorithm is probably pretty much blindly copied from 1370 * This algorithm is probably pretty much blindly copied from
1327 * locations like this one: https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos 1371 * locations like this one: https://www.slac.stanford.edu/comp/net/wan-mon/tutorial.html#mos
@@ -1336,19 +1380,19 @@ finish(int sig)
1336 * More links: 1380 * More links:
1337 * - https://confluence.slac.stanford.edu/display/IEPM/MOS 1381 * - https://confluence.slac.stanford.edu/display/IEPM/MOS
1338 */ 1382 */
1339 host->jitter=(host->jitter / (host->icmp_recv - 1)/1000); 1383 host->jitter = (host->jitter / (host->icmp_recv - 1) / 1000);
1340 1384
1341 /* 1385 /*
1342 * Take the average round trip latency (in milliseconds), add 1386 * Take the average round trip latency (in milliseconds), add
1343 * round trip jitter, but double the impact to latency 1387 * round trip jitter, but double the impact to latency
1344 * then add 10 for protocol latencies (in milliseconds). 1388 * then add 10 for protocol latencies (in milliseconds).
1345 */ 1389 */
1346 host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10; 1390 host->EffectiveLatency = (rta / 1000) + host->jitter * 2 + 10;
1347 1391
1348 if (host->EffectiveLatency < 160) { 1392 if (host->EffectiveLatency < 160) {
1349 R = 93.2 - (host->EffectiveLatency / 40); 1393 R = 93.2 - (host->EffectiveLatency / 40);
1350 } else { 1394 } else {
1351 R = 93.2 - ((host->EffectiveLatency - 120) / 10); 1395 R = 93.2 - ((host->EffectiveLatency - 120) / 10);
1352 } 1396 }
1353 1397
1354 // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a 1398 // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a
@@ -1360,12 +1404,12 @@ finish(int sig)
1360 } 1404 }
1361 1405
1362 host->score = R; 1406 host->score = R;
1363 host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R)); 1407 host->mos = 1 + ((0.035) * R) + ((.000007) * R * (R - 60) * (100 - R));
1364 } else { 1408 } else {
1365 host->jitter=0; 1409 host->jitter = 0;
1366 host->jitter_min=0; 1410 host->jitter_min = 0;
1367 host->jitter_max=0; 1411 host->jitter_max = 0;
1368 host->mos=0; 1412 host->mos = 0;
1369 } 1413 }
1370 1414
1371 host->pl = pl; 1415 host->pl = pl;
@@ -1379,62 +1423,62 @@ finish(int sig)
1379 1423
1380 /* Check which mode is on and do the warn / Crit stuff */ 1424 /* Check which mode is on and do the warn / Crit stuff */
1381 if (rta_mode) { 1425 if (rta_mode) {
1382 if(rta >= crit.rta) { 1426 if (rta >= crit.rta) {
1383 this_status = STATE_CRITICAL; 1427 this_status = STATE_CRITICAL;
1384 status = STATE_CRITICAL; 1428 status = STATE_CRITICAL;
1385 host->rta_status=STATE_CRITICAL; 1429 host->rta_status = STATE_CRITICAL;
1386 } else if(status!=STATE_CRITICAL && (rta >= warn.rta)) { 1430 } else if (status != STATE_CRITICAL && (rta >= warn.rta)) {
1387 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1431 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1388 status = STATE_WARNING; 1432 status = STATE_WARNING;
1389 host->rta_status=STATE_WARNING; 1433 host->rta_status = STATE_WARNING;
1390 } 1434 }
1391 } 1435 }
1392 1436
1393 if (pl_mode) { 1437 if (pl_mode) {
1394 if(pl >= crit.pl) { 1438 if (pl >= crit.pl) {
1395 this_status = STATE_CRITICAL; 1439 this_status = STATE_CRITICAL;
1396 status = STATE_CRITICAL; 1440 status = STATE_CRITICAL;
1397 host->pl_status=STATE_CRITICAL; 1441 host->pl_status = STATE_CRITICAL;
1398 } else if(status!=STATE_CRITICAL && (pl >= warn.pl)) { 1442 } else if (status != STATE_CRITICAL && (pl >= warn.pl)) {
1399 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1443 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1400 status = STATE_WARNING; 1444 status = STATE_WARNING;
1401 host->pl_status=STATE_WARNING; 1445 host->pl_status = STATE_WARNING;
1402 } 1446 }
1403 } 1447 }
1404 1448
1405 if (jitter_mode) { 1449 if (jitter_mode) {
1406 if(host->jitter >= crit.jitter) { 1450 if (host->jitter >= crit.jitter) {
1407 this_status = STATE_CRITICAL; 1451 this_status = STATE_CRITICAL;
1408 status = STATE_CRITICAL; 1452 status = STATE_CRITICAL;
1409 host->jitter_status=STATE_CRITICAL; 1453 host->jitter_status = STATE_CRITICAL;
1410 } else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) { 1454 } else if (status != STATE_CRITICAL && (host->jitter >= warn.jitter)) {
1411 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1455 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1412 status = STATE_WARNING; 1456 status = STATE_WARNING;
1413 host->jitter_status=STATE_WARNING; 1457 host->jitter_status = STATE_WARNING;
1414 } 1458 }
1415 } 1459 }
1416 1460
1417 if (mos_mode) { 1461 if (mos_mode) {
1418 if(host->mos <= crit.mos) { 1462 if (host->mos <= crit.mos) {
1419 this_status = STATE_CRITICAL; 1463 this_status = STATE_CRITICAL;
1420 status = STATE_CRITICAL; 1464 status = STATE_CRITICAL;
1421 host->mos_status=STATE_CRITICAL; 1465 host->mos_status = STATE_CRITICAL;
1422 } else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) { 1466 } else if (status != STATE_CRITICAL && (host->mos <= warn.mos)) {
1423 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1467 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1424 status = STATE_WARNING; 1468 status = STATE_WARNING;
1425 host->mos_status=STATE_WARNING; 1469 host->mos_status = STATE_WARNING;
1426 } 1470 }
1427 } 1471 }
1428 1472
1429 if (score_mode) { 1473 if (score_mode) {
1430 if(host->score <= crit.score) { 1474 if (host->score <= crit.score) {
1431 this_status = STATE_CRITICAL; 1475 this_status = STATE_CRITICAL;
1432 status = STATE_CRITICAL; 1476 status = STATE_CRITICAL;
1433 host->score_status=STATE_CRITICAL; 1477 host->score_status = STATE_CRITICAL;
1434 } else if(status!=STATE_CRITICAL && (host->score <= warn.score)) { 1478 } else if (status != STATE_CRITICAL && (host->score <= warn.score)) {
1435 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status); 1479 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1436 status = STATE_WARNING; 1480 status = STATE_WARNING;
1437 host->score_status=STATE_WARNING; 1481 host->score_status = STATE_WARNING;
1438 } 1482 }
1439 } 1483 }
1440 1484
@@ -1447,92 +1491,111 @@ finish(int sig)
1447 host = host->next; 1491 host = host->next;
1448 } 1492 }
1449 1493
1450
1451 /* this is inevitable */ 1494 /* this is inevitable */
1452 if(!targets_alive) status = STATE_CRITICAL; 1495 if (!targets_alive) {
1453 if(min_hosts_alive > -1) { 1496 status = STATE_CRITICAL;
1454 if(hosts_ok >= min_hosts_alive) status = STATE_OK; 1497 }
1455 else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; 1498 if (min_hosts_alive > -1) {
1499 if (hosts_ok >= min_hosts_alive) {
1500 status = STATE_OK;
1501 } else if ((hosts_ok + hosts_warn) >= min_hosts_alive) {
1502 status = STATE_WARNING;
1503 }
1456 } 1504 }
1457 printf("%s - ", status_string[status]); 1505 printf("%s - ", status_string[status]);
1458 1506
1459 host = list; 1507 host = list;
1460 while(host) { 1508 while (host) {
1509 if (debug) {
1510 puts("");
1511 }
1461 1512
1462 if(debug) puts(""); 1513 if (i) {
1463 if(i) { 1514 if (i < targets) {
1464 if(i < targets) printf(" :: "); 1515 printf(" :: ");
1465 else printf("\n"); 1516 } else {
1517 printf("\n");
1518 }
1466 } 1519 }
1520
1467 i++; 1521 i++;
1468 if(!host->icmp_recv) { 1522
1523 if (!host->icmp_recv) {
1469 status = STATE_CRITICAL; 1524 status = STATE_CRITICAL;
1470 host->rtmin=0; 1525 host->rtmin = 0;
1471 host->jitter_min=0; 1526 host->jitter_min = 0;
1472 if(host->flags & FLAG_LOST_CAUSE) { 1527
1528 if (host->flags & FLAG_LOST_CAUSE) {
1473 char address[INET6_ADDRSTRLEN]; 1529 char address[INET6_ADDRSTRLEN];
1474 parse_address(&host->error_addr, address, sizeof(address)); 1530 parse_address(&host->error_addr, address, sizeof(address));
1475 printf("%s: %s @ %s. rta nan, lost %d%%", 1531 printf("%s: %s @ %s. rta nan, lost %d%%", host->name, get_icmp_error_msg(host->icmp_type, host->icmp_code), address, 100);
1476 host->name,
1477 get_icmp_error_msg(host->icmp_type, host->icmp_code),
1478 address,
1479 100);
1480 } else { /* not marked as lost cause, so we have no flags for it */ 1532 } else { /* not marked as lost cause, so we have no flags for it */
1481 printf("%s: rta nan, lost 100%%", host->name); 1533 printf("%s: rta nan, lost 100%%", host->name);
1482 } 1534 }
1483 } else { /* !icmp_recv */ 1535 } else { /* !icmp_recv */
1484 printf("%s", host->name); 1536 printf("%s", host->name);
1485 /* rta text output */ 1537 /* rta text output */
1486 if (rta_mode) { 1538 if (rta_mode) {
1487 if (status == STATE_OK) 1539 if (status == STATE_OK) {
1488 printf(" rta %0.3fms", host->rta / 1000); 1540 printf(" rta %0.3fms", host->rta / 1000);
1489 else if (status==STATE_WARNING && host->rta_status==status) 1541 } else if (status == STATE_WARNING && host->rta_status == status) {
1490 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000); 1542 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta / 1000);
1491 else if (status==STATE_CRITICAL && host->rta_status==status) 1543 } else if (status == STATE_CRITICAL && host->rta_status == status) {
1492 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000); 1544 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta / 1000);
1545 }
1493 } 1546 }
1547
1494 /* pl text output */ 1548 /* pl text output */
1495 if (pl_mode) { 1549 if (pl_mode) {
1496 if (status == STATE_OK) 1550 if (status == STATE_OK) {
1497 printf(" lost %u%%", host->pl); 1551 printf(" lost %u%%", host->pl);
1498 else if (status==STATE_WARNING && host->pl_status==status) 1552 } else if (status == STATE_WARNING && host->pl_status == status) {
1499 printf(" lost %u%% > %u%%", host->pl, warn.pl); 1553 printf(" lost %u%% > %u%%", host->pl, warn.pl);
1500 else if (status==STATE_CRITICAL && host->pl_status==status) 1554 } else if (status == STATE_CRITICAL && host->pl_status == status) {
1501 printf(" lost %u%% > %u%%", host->pl, crit.pl); 1555 printf(" lost %u%% > %u%%", host->pl, crit.pl);
1556 }
1502 } 1557 }
1558
1503 /* jitter text output */ 1559 /* jitter text output */
1504 if (jitter_mode) { 1560 if (jitter_mode) {
1505 if (status == STATE_OK) 1561 if (status == STATE_OK) {
1506 printf(" jitter %0.3fms", (float)host->jitter); 1562 printf(" jitter %0.3fms", (float)host->jitter);
1507 else if (status==STATE_WARNING && host->jitter_status==status) 1563 } else if (status == STATE_WARNING && host->jitter_status == status) {
1508 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter); 1564 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter);
1509 else if (status==STATE_CRITICAL && host->jitter_status==status) 1565 } else if (status == STATE_CRITICAL && host->jitter_status == status) {
1510 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter); 1566 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter);
1567 }
1511 } 1568 }
1569
1512 /* mos text output */ 1570 /* mos text output */
1513 if (mos_mode) { 1571 if (mos_mode) {
1514 if (status == STATE_OK) 1572 if (status == STATE_OK) {
1515 printf(" MOS %0.1f", (float)host->mos); 1573 printf(" MOS %0.1f", (float)host->mos);
1516 else if (status==STATE_WARNING && host->mos_status==status) 1574 } else if (status == STATE_WARNING && host->mos_status == status) {
1517 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos); 1575 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos);
1518 else if (status==STATE_CRITICAL && host->mos_status==status) 1576 } else if (status == STATE_CRITICAL && host->mos_status == status) {
1519 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos); 1577 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos);
1578 }
1520 } 1579 }
1580
1521 /* score text output */ 1581 /* score text output */
1522 if (score_mode) { 1582 if (score_mode) {
1523 if (status == STATE_OK) 1583 if (status == STATE_OK) {
1524 printf(" Score %u", (int)host->score); 1584 printf(" Score %u", (int)host->score);
1525 else if (status==STATE_WARNING && host->score_status==status ) 1585 } else if (status == STATE_WARNING && host->score_status == status) {
1526 printf(" Score %u < %u", (int)host->score, (int)warn.score); 1586 printf(" Score %u < %u", (int)host->score, (int)warn.score);
1527 else if (status==STATE_CRITICAL && host->score_status==status ) 1587 } else if (status == STATE_CRITICAL && host->score_status == status) {
1528 printf(" Score %u < %u", (int)host->score, (int)crit.score); 1588 printf(" Score %u < %u", (int)host->score, (int)crit.score);
1589 }
1529 } 1590 }
1591
1530 /* order statis text output */ 1592 /* order statis text output */
1531 if (order_mode) { 1593 if (order_mode) {
1532 if (status == STATE_OK) 1594 if (status == STATE_OK) {
1533 printf(" Packets in order"); 1595 printf(" Packets in order");
1534 else if (status==STATE_CRITICAL && host->order_status==status) 1596 } else if (status == STATE_CRITICAL && host->order_status == status) {
1535 printf(" Packets out of order"); 1597 printf(" Packets out of order");
1598 }
1536 } 1599 }
1537 } 1600 }
1538 host = host->next; 1601 host = host->next;
@@ -1540,25 +1603,24 @@ finish(int sig)
1540 1603
1541 /* iterate once more for pretty perfparse output */ 1604 /* iterate once more for pretty perfparse output */
1542 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) { 1605 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1543 printf("|"); 1606 printf("|");
1544 } 1607 }
1545 i = 0; 1608 i = 0;
1546 host = list; 1609 host = list;
1547 while(host) { 1610 while (host) {
1548 if(debug) puts(""); 1611 if (debug) {
1612 puts("");
1613 }
1549 1614
1550 if (rta_mode) { 1615 if (rta_mode) {
1551 if (host->pl<100) { 1616 if (host->pl < 100) {
1552 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", 1617 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", (targets > 1) ? host->name : "",
1553 (targets > 1) ? host->name : "", 1618 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, (targets > 1) ? host->name : "",
1554 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1619 (float)host->rtmax / 1000, (targets > 1) ? host->name : "",
1555 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1620 (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1556 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1557 } else { 1621 } else {
1558 printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", 1622 printf("%srta=U;;;; %srtmax=U;;;; %srtmin=U;;;; ", (targets > 1) ? host->name : "", (targets > 1) ? host->name : "",
1559 (targets > 1) ? host->name : "", 1623 (targets > 1) ? host->name : "");
1560 (targets > 1) ? host->name : "",
1561 (targets > 1) ? host->name : "");
1562 } 1624 }
1563 } 1625 }
1564 1626
@@ -1567,43 +1629,28 @@ finish(int sig)
1567 } 1629 }
1568 1630
1569 if (jitter_mode) { 1631 if (jitter_mode) {
1570 if (host->pl<100) { 1632 if (host->pl < 100) {
1571 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ", 1633 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ",
1572 (targets > 1) ? host->name : "", 1634 (targets > 1) ? host->name : "", (float)host->jitter, (float)warn.jitter, (float)crit.jitter,
1573 (float)host->jitter, 1635 (targets > 1) ? host->name : "", (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1574 (float)warn.jitter, 1636 (float)host->jitter_min / 1000);
1575 (float)crit.jitter,
1576 (targets > 1) ? host->name : "",
1577 (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1578 (float)host->jitter_min / 1000
1579 );
1580 } else { 1637 } else {
1581 printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", 1638 printf("%sjitter_avg=U;;;; %sjitter_max=U;;;; %sjitter_min=U;;;; ", (targets > 1) ? host->name : "",
1582 (targets > 1) ? host->name : "", 1639 (targets > 1) ? host->name : "", (targets > 1) ? host->name : "");
1583 (targets > 1) ? host->name : "",
1584 (targets > 1) ? host->name : "");
1585 } 1640 }
1586 } 1641 }
1587 1642
1588 if (mos_mode) { 1643 if (mos_mode) {
1589 if (host->pl<100) { 1644 if (host->pl < 100) {
1590 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", 1645 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ", (targets > 1) ? host->name : "", (float)host->mos, (float)warn.mos, (float)crit.mos);
1591 (targets > 1) ? host->name : "",
1592 (float)host->mos,
1593 (float)warn.mos,
1594 (float)crit.mos);
1595 } else { 1646 } else {
1596 printf("%smos=U;;;; ", (targets > 1) ? host->name : ""); 1647 printf("%smos=U;;;; ", (targets > 1) ? host->name : "");
1597 } 1648 }
1598 } 1649 }
1599 1650
1600 if (score_mode) { 1651 if (score_mode) {
1601 if (host->pl<100) { 1652 if (host->pl < 100) {
1602 printf("%sscore=%u;%u;%u;0;100 ", 1653 printf("%sscore=%u;%u;%u;0;100 ", (targets > 1) ? host->name : "", (int)host->score, (int)warn.score, (int)crit.score);
1603 (targets > 1) ? host->name : "",
1604 (int)host->score,
1605 (int)warn.score,
1606 (int)crit.score);
1607 } else { 1654 } else {
1608 printf("%sscore=U;;;; ", (targets > 1) ? host->name : ""); 1655 printf("%sscore=U;;;; ", (targets > 1) ? host->name : "");
1609 } 1656 }
@@ -1612,35 +1659,38 @@ finish(int sig)
1612 host = host->next; 1659 host = host->next;
1613 } 1660 }
1614 1661
1615 if(min_hosts_alive > -1) { 1662 if (min_hosts_alive > -1) {
1616 if(hosts_ok >= min_hosts_alive) status = STATE_OK; 1663 if (hosts_ok >= min_hosts_alive) {
1617 else if((hosts_ok + hosts_warn) >= min_hosts_alive) status = STATE_WARNING; 1664 status = STATE_OK;
1665 } else if ((hosts_ok + hosts_warn) >= min_hosts_alive) {
1666 status = STATE_WARNING;
1667 }
1618 } 1668 }
1619 1669
1620 /* finish with an empty line */ 1670 /* finish with an empty line */
1621 puts(""); 1671 puts("");
1622 if(debug) printf("targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", 1672 if (debug) {
1623 targets, targets_alive, hosts_ok, hosts_warn, min_hosts_alive); 1673 printf("targets: %u, targets_alive: %u, hosts_ok: %u, hosts_warn: %u, min_hosts_alive: %i\n", targets, targets_alive, hosts_ok,
1674 hosts_warn, min_hosts_alive);
1675 }
1624 1676
1625 exit(status); 1677 exit(status);
1626} 1678}
1627 1679
1628static u_int 1680static u_int get_timevaldiff(struct timeval *early, struct timeval *later) {
1629get_timevaldiff(struct timeval *early, struct timeval *later)
1630{
1631 u_int ret; 1681 u_int ret;
1632 struct timeval now; 1682 struct timeval now;
1633 1683
1634 if(!later) { 1684 if (!later) {
1635 gettimeofday(&now, &tz); 1685 gettimeofday(&now, &tz);
1636 later = &now; 1686 later = &now;
1637 } 1687 }
1638 if(!early) early = &prog_start; 1688 if (!early) {
1689 early = &prog_start;
1690 }
1639 1691
1640 /* if early > later we return 0 so as to indicate a timeout */ 1692 /* if early > later we return 0 so as to indicate a timeout */
1641 if(early->tv_sec > later->tv_sec || 1693 if (early->tv_sec > later->tv_sec || (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec)) {
1642 (early->tv_sec == later->tv_sec && early->tv_usec > later->tv_usec))
1643 {
1644 return 0; 1694 return 0;
1645 } 1695 }
1646 ret = (later->tv_sec - early->tv_sec) * 1000000; 1696 ret = (later->tv_sec - early->tv_sec) * 1000000;
@@ -1649,63 +1699,58 @@ get_timevaldiff(struct timeval *early, struct timeval *later)
1649 return ret; 1699 return ret;
1650} 1700}
1651 1701
1652static int 1702static int add_target_ip(char *arg, struct sockaddr_storage *in) {
1653add_target_ip(char *arg, struct sockaddr_storage *in)
1654{
1655 struct rta_host *host; 1703 struct rta_host *host;
1656 struct sockaddr_in *sin, *host_sin; 1704 struct sockaddr_in *sin, *host_sin;
1657 struct sockaddr_in6 *sin6, *host_sin6; 1705 struct sockaddr_in6 *sin6, *host_sin6;
1658 1706
1659 if (address_family == AF_INET) 1707 if (address_family == AF_INET) {
1660 sin = (struct sockaddr_in *)in; 1708 sin = (struct sockaddr_in *)in;
1661 else 1709 } else {
1662 sin6 = (struct sockaddr_in6 *)in; 1710 sin6 = (struct sockaddr_in6 *)in;
1663 1711 }
1664
1665 1712
1666 /* disregard obviously stupid addresses 1713 /* disregard obviously stupid addresses
1667 * (I didn't find an ipv6 equivalent to INADDR_NONE) */ 1714 * (I didn't find an ipv6 equivalent to INADDR_NONE) */
1668 if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE 1715 if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE || sin->sin_addr.s_addr == INADDR_ANY))) ||
1669 || sin->sin_addr.s_addr == INADDR_ANY))) 1716 (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1670 || (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1671 return -1; 1717 return -1;
1672 } 1718 }
1673 1719
1674 /* no point in adding two identical IP's, so don't. ;) */ 1720 /* no point in adding two identical IP's, so don't. ;) */
1675 host = list; 1721 host = list;
1676 while(host) { 1722 while (host) {
1677 host_sin = (struct sockaddr_in *)&host->saddr_in; 1723 host_sin = (struct sockaddr_in *)&host->saddr_in;
1678 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; 1724 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1679 1725
1680 if( (address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) 1726 if ((address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr) ||
1681 || (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) { 1727 (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
1682 if(debug) printf("Identical IP already exists. Not adding %s\n", arg); 1728 if (debug) {
1729 printf("Identical IP already exists. Not adding %s\n", arg);
1730 }
1683 return -1; 1731 return -1;
1684 } 1732 }
1685 host = host->next; 1733 host = host->next;
1686 } 1734 }
1687 1735
1688 /* add the fresh ip */ 1736 /* add the fresh ip */
1689 host = (struct rta_host*)malloc(sizeof(struct rta_host)); 1737 host = (struct rta_host *)malloc(sizeof(struct rta_host));
1690 if(!host) { 1738 if (!host) {
1691 char straddr[INET6_ADDRSTRLEN]; 1739 char straddr[INET6_ADDRSTRLEN];
1692 parse_address((struct sockaddr_storage*)&in, straddr, sizeof(straddr)); 1740 parse_address((struct sockaddr_storage *)&in, straddr, sizeof(straddr));
1693 crash("add_target_ip(%s, %s): malloc(%lu) failed", 1741 crash("add_target_ip(%s, %s): malloc(%lu) failed", arg, straddr, sizeof(struct rta_host));
1694 arg, straddr, sizeof(struct rta_host));
1695 } 1742 }
1696 memset(host, 0, sizeof(struct rta_host)); 1743 memset(host, 0, sizeof(struct rta_host));
1697 1744
1698 /* set the values. use calling name for output */ 1745 /* set the values. use calling name for output */
1699 host->name = strdup(arg); 1746 host->name = strdup(arg);
1700 1747
1701
1702 /* fill out the sockaddr_storage struct */ 1748 /* fill out the sockaddr_storage struct */
1703 if(address_family == AF_INET) { 1749 if (address_family == AF_INET) {
1704 host_sin = (struct sockaddr_in *)&host->saddr_in; 1750 host_sin = (struct sockaddr_in *)&host->saddr_in;
1705 host_sin->sin_family = AF_INET; 1751 host_sin->sin_family = AF_INET;
1706 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr; 1752 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
1707 } 1753 } else {
1708 else {
1709 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in; 1754 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1710 host_sin6->sin6_family = AF_INET6; 1755 host_sin6->sin6_family = AF_INET6;
1711 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); 1756 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
@@ -1714,22 +1759,24 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1714 /* fill out the sockaddr_in struct */ 1759 /* fill out the sockaddr_in struct */
1715 host->rtmin = INFINITY; 1760 host->rtmin = INFINITY;
1716 host->rtmax = 0; 1761 host->rtmax = 0;
1717 host->jitter=0; 1762 host->jitter = 0;
1718 host->jitter_max=0; 1763 host->jitter_max = 0;
1719 host->jitter_min=INFINITY; 1764 host->jitter_min = INFINITY;
1720 host->last_tdiff=0; 1765 host->last_tdiff = 0;
1721 host->order_status=STATE_OK; 1766 host->order_status = STATE_OK;
1722 host->last_icmp_seq=0; 1767 host->last_icmp_seq = 0;
1723 host->rta_status=0; 1768 host->rta_status = 0;
1724 host->pl_status=0; 1769 host->pl_status = 0;
1725 host->jitter_status=0; 1770 host->jitter_status = 0;
1726 host->mos_status=0; 1771 host->mos_status = 0;
1727 host->score_status=0; 1772 host->score_status = 0;
1728 host->pl_status=0; 1773 host->pl_status = 0;
1729 1774
1730 1775 if (!list) {
1731 if(!list) list = cursor = host; 1776 list = cursor = host;
1732 else cursor->next = host; 1777 } else {
1778 cursor->next = host;
1779 }
1733 1780
1734 cursor = host; 1781 cursor = host;
1735 targets++; 1782 targets++;
@@ -1738,9 +1785,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1738} 1785}
1739 1786
1740/* wrapper for add_target_ip */ 1787/* wrapper for add_target_ip */
1741static int 1788static int add_target(char *arg) {
1742add_target(char *arg)
1743{
1744 int error, result = -1; 1789 int error, result = -1;
1745 struct sockaddr_storage ip; 1790 struct sockaddr_storage ip;
1746 struct addrinfo hints, *res, *p; 1791 struct addrinfo hints, *res, *p;
@@ -1754,14 +1799,14 @@ add_target(char *arg)
1754 sin = (struct sockaddr_in *)&ip; 1799 sin = (struct sockaddr_in *)&ip;
1755 result = inet_pton(address_family, arg, &sin->sin_addr); 1800 result = inet_pton(address_family, arg, &sin->sin_addr);
1756#ifdef USE_IPV6 1801#ifdef USE_IPV6
1757 if( result != 1 ){ 1802 if (result != 1) {
1758 address_family = AF_INET6; 1803 address_family = AF_INET6;
1759 sin6 = (struct sockaddr_in6 *)&ip; 1804 sin6 = (struct sockaddr_in6 *)&ip;
1760 result = inet_pton(address_family, arg, &sin6->sin6_addr); 1805 result = inet_pton(address_family, arg, &sin6->sin6_addr);
1761 } 1806 }
1762#endif 1807#endif
1763 /* If we don't find any valid addresses, we still don't know the address_family */ 1808 /* If we don't find any valid addresses, we still don't know the address_family */
1764 if ( result != 1) { 1809 if (result != 1) {
1765 address_family = -1; 1810 address_family = -1;
1766 } 1811 }
1767 break; 1812 break;
@@ -1773,15 +1818,15 @@ add_target(char *arg)
1773 sin6 = (struct sockaddr_in6 *)&ip; 1818 sin6 = (struct sockaddr_in6 *)&ip;
1774 result = inet_pton(address_family, arg, &sin6->sin6_addr); 1819 result = inet_pton(address_family, arg, &sin6->sin6_addr);
1775 break; 1820 break;
1776 default: crash("Address family not supported"); 1821 default:
1822 crash("Address family not supported");
1777 } 1823 }
1778 1824
1779 /* don't resolve if we don't have to */ 1825 /* don't resolve if we don't have to */
1780 if(result == 1) { 1826 if (result == 1) {
1781 /* don't add all ip's if we were given a specific one */ 1827 /* don't add all ip's if we were given a specific one */
1782 return add_target_ip(arg, &ip); 1828 return add_target_ip(arg, &ip);
1783 } 1829 } else {
1784 else {
1785 errno = 0; 1830 errno = 0;
1786 memset(&hints, 0, sizeof(hints)); 1831 memset(&hints, 0, sizeof(hints));
1787 if (address_family == -1) { 1832 if (address_family == -1) {
@@ -1790,7 +1835,7 @@ add_target(char *arg)
1790 hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6; 1835 hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6;
1791 } 1836 }
1792 hints.ai_socktype = SOCK_RAW; 1837 hints.ai_socktype = SOCK_RAW;
1793 if((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) { 1838 if ((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) {
1794 errno = 0; 1839 errno = 0;
1795 crash("Failed to resolve %s: %s", arg, gai_strerror(error)); 1840 crash("Failed to resolve %s: %s", arg, gai_strerror(error));
1796 return -1; 1841 return -1;
@@ -1799,13 +1844,15 @@ add_target(char *arg)
1799 } 1844 }
1800 1845
1801 /* possibly add all the IP's as targets */ 1846 /* possibly add all the IP's as targets */
1802 for(p = res; p != NULL; p = p->ai_next) { 1847 for (p = res; p != NULL; p = p->ai_next) {
1803 memcpy(&ip, p->ai_addr, p->ai_addrlen); 1848 memcpy(&ip, p->ai_addr, p->ai_addrlen);
1804 add_target_ip(arg, &ip); 1849 add_target_ip(arg, &ip);
1805 1850
1806 /* this is silly, but it works */ 1851 /* this is silly, but it works */
1807 if(mode == MODE_HOSTCHECK || mode == MODE_ALL) { 1852 if (mode == MODE_HOSTCHECK || mode == MODE_ALL) {
1808 if(debug > 2) printf("mode: %d\n", mode); 1853 if (debug > 2) {
1854 printf("mode: %d\n", mode);
1855 }
1809 continue; 1856 continue;
1810 } 1857 }
1811 break; 1858 break;
@@ -1815,24 +1862,22 @@ add_target(char *arg)
1815 return 0; 1862 return 0;
1816} 1863}
1817 1864
1818static void 1865static void set_source_ip(char *arg) {
1819set_source_ip(char *arg)
1820{
1821 struct sockaddr_in src; 1866 struct sockaddr_in src;
1822 1867
1823 memset(&src, 0, sizeof(src)); 1868 memset(&src, 0, sizeof(src));
1824 src.sin_family = address_family; 1869 src.sin_family = address_family;
1825 if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) 1870 if ((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) {
1826 src.sin_addr.s_addr = get_ip_address(arg); 1871 src.sin_addr.s_addr = get_ip_address(arg);
1827 if(bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) 1872 }
1873 if (bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) {
1828 crash("Cannot bind to IP address %s", arg); 1874 crash("Cannot bind to IP address %s", arg);
1875 }
1829} 1876}
1830 1877
1831/* TODO: Move this to netutils.c and also change check_dhcp to use that. */ 1878/* TODO: Move this to netutils.c and also change check_dhcp to use that. */
1832static in_addr_t 1879static in_addr_t get_ip_address(const char *ifname) {
1833get_ip_address(const char *ifname) 1880 // TODO: Rewrite this so the function return an error and we exit somewhere else
1834{
1835 // TODO: Rewrite this so the function return an error and we exit somewhere else
1836 struct sockaddr_in ip; 1881 struct sockaddr_in ip;
1837 ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy 1882 ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy
1838#if defined(SIOCGIFADDR) 1883#if defined(SIOCGIFADDR)
@@ -1842,12 +1887,13 @@ get_ip_address(const char *ifname)
1842 1887
1843 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 1888 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1844 1889
1845 if(ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1) 1890 if (ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1) {
1846 crash("Cannot determine IP address of interface %s", ifname); 1891 crash("Cannot determine IP address of interface %s", ifname);
1892 }
1847 1893
1848 memcpy(&ip, &ifr.ifr_addr, sizeof(ip)); 1894 memcpy(&ip, &ifr.ifr_addr, sizeof(ip));
1849#else 1895#else
1850 (void) ifname; 1896 (void)ifname;
1851 errno = 0; 1897 errno = 0;
1852 crash("Cannot get interface IP address on this platform."); 1898 crash("Cannot get interface IP address on this platform.");
1853#endif 1899#endif
@@ -1860,63 +1906,84 @@ get_ip_address(const char *ifname)
1860 * s = seconds 1906 * s = seconds
1861 * return value is in microseconds 1907 * return value is in microseconds
1862 */ 1908 */
1863static u_int 1909static u_int get_timevar(const char *str) {
1864get_timevar(const char *str)
1865{
1866 char p, u, *ptr; 1910 char p, u, *ptr;
1867 size_t len; 1911 size_t len;
1868 u_int i, d; /* integer and decimal, respectively */ 1912 u_int i, d; /* integer and decimal, respectively */
1869 u_int factor = 1000; /* default to milliseconds */ 1913 u_int factor = 1000; /* default to milliseconds */
1870 1914
1871 if(!str) return 0; 1915 if (!str) {
1916 return 0;
1917 }
1872 len = strlen(str); 1918 len = strlen(str);
1873 if(!len) return 0; 1919 if (!len) {
1920 return 0;
1921 }
1874 1922
1875 /* unit might be given as ms|m (millisec), 1923 /* unit might be given as ms|m (millisec),
1876 * us|u (microsec) or just plain s, for seconds */ 1924 * us|u (microsec) or just plain s, for seconds */
1877 p = '\0'; 1925 p = '\0';
1878 u = str[len - 1]; 1926 u = str[len - 1];
1879 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; 1927 if (len >= 2 && !isdigit((int)str[len - 2])) {
1880 if(p && u == 's') u = p; 1928 p = str[len - 2];
1881 else if(!p) p = u; 1929 }
1882 if(debug > 2) printf("evaluating %s, u: %c, p: %c\n", str, u, p); 1930 if (p && u == 's') {
1931 u = p;
1932 } else if (!p) {
1933 p = u;
1934 }
1935 if (debug > 2) {
1936 printf("evaluating %s, u: %c, p: %c\n", str, u, p);
1937 }
1883 1938
1884 if(u == 'u') factor = 1; /* microseconds */ 1939 if (u == 'u') {
1885 else if(u == 'm') factor = 1000; /* milliseconds */ 1940 factor = 1; /* microseconds */
1886 else if(u == 's') factor = 1000000; /* seconds */ 1941 } else if (u == 'm') {
1887 if(debug > 2) printf("factor is %u\n", factor); 1942 factor = 1000; /* milliseconds */
1943 } else if (u == 's') {
1944 factor = 1000000; /* seconds */
1945 }
1946 if (debug > 2) {
1947 printf("factor is %u\n", factor);
1948 }
1888 1949
1889 i = strtoul(str, &ptr, 0); 1950 i = strtoul(str, &ptr, 0);
1890 if(!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) 1951 if (!ptr || *ptr != '.' || strlen(ptr) < 2 || factor == 1) {
1891 return i * factor; 1952 return i * factor;
1953 }
1892 1954
1893 /* time specified in usecs can't have decimal points, so ignore them */ 1955 /* time specified in usecs can't have decimal points, so ignore them */
1894 if(factor == 1) return i; 1956 if (factor == 1) {
1957 return i;
1958 }
1895 1959
1896 d = strtoul(ptr + 1, NULL, 0); 1960 d = strtoul(ptr + 1, NULL, 0);
1897 1961
1898 /* d is decimal, so get rid of excess digits */ 1962 /* d is decimal, so get rid of excess digits */
1899 while(d >= factor) d /= 10; 1963 while (d >= factor) {
1964 d /= 10;
1965 }
1900 1966
1901 /* the last parenthesis avoids floating point exceptions. */ 1967 /* the last parenthesis avoids floating point exceptions. */
1902 return ((i * factor) + (d * (factor / 10))); 1968 return ((i * factor) + (d * (factor / 10)));
1903} 1969}
1904 1970
1905/* not too good at checking errors, but it'll do (main() should barfe on -1) */ 1971/* not too good at checking errors, but it'll do (main() should barfe on -1) */
1906static int 1972static int get_threshold(char *str, threshold *th) {
1907get_threshold(char *str, threshold *th)
1908{
1909 char *p = NULL, i = 0; 1973 char *p = NULL, i = 0;
1910 1974
1911 if(!str || !strlen(str) || !th) return -1; 1975 if (!str || !strlen(str) || !th) {
1976 return -1;
1977 }
1912 1978
1913 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */ 1979 /* pointer magic slims code by 10 lines. i is bof-stop on stupid libc's */
1914 p = &str[strlen(str) - 1]; 1980 p = &str[strlen(str) - 1];
1915 while(p != &str[1]) { 1981 while (p != &str[1]) {
1916 if(*p == '%') *p = '\0'; 1982 if (*p == '%') {
1917 else if(*p == ',' && i) { 1983 *p = '\0';
1918 *p = '\0'; /* reset it so get_timevar(str) works nicely later */ 1984 } else if (*p == ',' && i) {
1919 th->pl = (unsigned char)strtoul(p+1, NULL, 0); 1985 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1986 th->pl = (unsigned char)strtoul(p + 1, NULL, 0);
1920 break; 1987 break;
1921 } 1988 }
1922 i = 1; 1989 i = 1;
@@ -1924,10 +1991,16 @@ get_threshold(char *str, threshold *th)
1924 } 1991 }
1925 th->rta = get_timevar(str); 1992 th->rta = get_timevar(str);
1926 1993
1927 if(!th->rta) return -1; 1994 if (!th->rta) {
1995 return -1;
1996 }
1928 1997
1929 if(th->rta > MAXTTL * 1000000) th->rta = MAXTTL * 1000000; 1998 if (th->rta > MAXTTL * 1000000) {
1930 if(th->pl > 100) th->pl = 100; 1999 th->rta = MAXTTL * 1000000;
2000 }
2001 if (th->pl > 100) {
2002 th->pl = 100;
2003 }
1931 2004
1932 return 0; 2005 return 0;
1933} 2006}
@@ -1943,8 +2016,9 @@ get_threshold(char *str, threshold *th)
1943 * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively) 2016 * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively)
1944 */ 2017 */
1945static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) { 2018static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) {
1946 if (!str || !length || !warn || !crit) return false; 2019 if (!str || !length || !warn || !crit) {
1947 2020 return false;
2021 }
1948 2022
1949 // p points to the last char in str 2023 // p points to the last char in str
1950 char *p = &str[length - 1]; 2024 char *p = &str[length - 1];
@@ -1952,18 +2026,17 @@ static bool get_threshold2(char *str, size_t length, threshold *warn, threshold
1952 // first_iteration is bof-stop on stupid libc's 2026 // first_iteration is bof-stop on stupid libc's
1953 bool first_iteration = true; 2027 bool first_iteration = true;
1954 2028
1955 while(p != &str[0]) { 2029 while (p != &str[0]) {
1956 if( (*p == 'm') || (*p == '%') ) { 2030 if ((*p == 'm') || (*p == '%')) {
1957 *p = '\0'; 2031 *p = '\0';
1958 } else if(*p == ',' && !first_iteration) { 2032 } else if (*p == ',' && !first_iteration) {
1959 *p = '\0'; /* reset it so get_timevar(str) works nicely later */ 2033 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1960 2034
1961 char *start_of_value = p + 1; 2035 char *start_of_value = p + 1;
1962 2036
1963 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)){ 2037 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)) {
1964 return false; 2038 return false;
1965 } 2039 }
1966
1967 } 2040 }
1968 first_iteration = false; 2041 first_iteration = false;
1969 p--; 2042 p--;
@@ -1976,22 +2049,22 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre
1976 char *resultChecker = {0}; 2049 char *resultChecker = {0};
1977 2050
1978 switch (mode) { 2051 switch (mode) {
1979 case const_rta_mode: 2052 case const_rta_mode:
1980 thr->rta = strtod(s, &resultChecker) * 1000; 2053 thr->rta = strtod(s, &resultChecker) * 1000;
1981 break; 2054 break;
1982 case const_packet_loss_mode: 2055 case const_packet_loss_mode:
1983 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0); 2056 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0);
1984 break; 2057 break;
1985 case const_jitter_mode: 2058 case const_jitter_mode:
1986 thr->jitter = strtod(s, &resultChecker); 2059 thr->jitter = strtod(s, &resultChecker);
1987 2060
1988 break; 2061 break;
1989 case const_mos_mode: 2062 case const_mos_mode:
1990 thr->mos = strtod(s, &resultChecker); 2063 thr->mos = strtod(s, &resultChecker);
1991 break; 2064 break;
1992 case const_score_mode: 2065 case const_score_mode:
1993 thr->score = strtod(s, &resultChecker); 2066 thr->score = strtod(s, &resultChecker);
1994 break; 2067 break;
1995 } 2068 }
1996 2069
1997 if (resultChecker == s) { 2070 if (resultChecker == s) {
@@ -2007,123 +2080,117 @@ static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, thre
2007 return true; 2080 return true;
2008} 2081}
2009 2082
2010unsigned short 2083unsigned short icmp_checksum(uint16_t *p, size_t n) {
2011icmp_checksum(uint16_t *p, size_t n)
2012{
2013 unsigned short cksum; 2084 unsigned short cksum;
2014 long sum = 0; 2085 long sum = 0;
2015 2086
2016 /* sizeof(uint16_t) == 2 */ 2087 /* sizeof(uint16_t) == 2 */
2017 while(n >= 2) { 2088 while (n >= 2) {
2018 sum += *(p++); 2089 sum += *(p++);
2019 n -= 2; 2090 n -= 2;
2020 } 2091 }
2021 2092
2022 /* mop up the occasional odd byte */ 2093 /* mop up the occasional odd byte */
2023 if(n == 1) sum += *((uint8_t *)p -1); 2094 if (n == 1) {
2095 sum += *((uint8_t *)p - 1);
2096 }
2024 2097
2025 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 2098 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
2026 sum += (sum >> 16); /* add carry */ 2099 sum += (sum >> 16); /* add carry */
2027 cksum = ~sum; /* ones-complement, trunc to 16 bits */ 2100 cksum = ~sum; /* ones-complement, trunc to 16 bits */
2028 2101
2029 return cksum; 2102 return cksum;
2030} 2103}
2031 2104
2032void 2105void print_help(void) {
2033print_help(void)
2034{
2035 /*print_revision (progname);*/ /* FIXME: Why? */ 2106 /*print_revision (progname);*/ /* FIXME: Why? */
2036 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); 2107 printf("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
2037 2108
2038 printf (COPYRIGHT, copyright, email); 2109 printf(COPYRIGHT, copyright, email);
2039 2110
2040 printf ("\n\n"); 2111 printf("\n\n");
2041 2112
2042 print_usage (); 2113 print_usage();
2043 2114
2044 printf (UT_HELP_VRSN); 2115 printf(UT_HELP_VRSN);
2045 printf (UT_EXTRA_OPTS); 2116 printf(UT_EXTRA_OPTS);
2046 2117
2047 printf (" %s\n", "-H"); 2118 printf(" %s\n", "-H");
2048 printf (" %s\n", _("specify a target")); 2119 printf(" %s\n", _("specify a target"));
2049 printf (" %s\n", "[-4|-6]"); 2120 printf(" %s\n", "[-4|-6]");
2050 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); 2121 printf(" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets"));
2051 printf (" %s\n", "-w"); 2122 printf(" %s\n", "-w");
2052 printf (" %s", _("warning threshold (currently ")); 2123 printf(" %s", _("warning threshold (currently "));
2053 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); 2124 printf("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
2054 printf (" %s\n", "-c"); 2125 printf(" %s\n", "-c");
2055 printf (" %s", _("critical threshold (currently ")); 2126 printf(" %s", _("critical threshold (currently "));
2056 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); 2127 printf("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
2057 2128
2058 printf (" %s\n", "-R"); 2129 printf(" %s\n", "-R");
2059 printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms")); 2130 printf(" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"));
2060 printf (" %s\n", "-P"); 2131 printf(" %s\n", "-P");
2061 printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %")); 2132 printf(" %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
2062 printf (" %s\n", "-J"); 2133 printf(" %s\n", "-J");
2063 printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms ")); 2134 printf(" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
2064 printf (" %s\n", "-M"); 2135 printf(" %s\n", "-M");
2065 printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0")); 2136 printf(" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"));
2066 printf (" %s\n", "-S"); 2137 printf(" %s\n", "-S");
2067 printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 ")); 2138 printf(" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 "));
2068 printf (" %s\n", "-O"); 2139 printf(" %s\n", "-O");
2069 printf (" %s\n", _("detect out of order ICMP packts ")); 2140 printf(" %s\n", _("detect out of order ICMP packts "));
2070 printf (" %s\n", "-H"); 2141 printf(" %s\n", "-H");
2071 printf (" %s\n", _("specify a target")); 2142 printf(" %s\n", _("specify a target"));
2072 printf (" %s\n", "-s"); 2143 printf(" %s\n", "-s");
2073 printf (" %s\n", _("specify a source IP address or device name")); 2144 printf(" %s\n", _("specify a source IP address or device name"));
2074 printf (" %s\n", "-n"); 2145 printf(" %s\n", "-n");
2075 printf (" %s", _("number of packets to send (currently ")); 2146 printf(" %s", _("number of packets to send (currently "));
2076 printf ("%u)\n",packets); 2147 printf("%u)\n", packets);
2077 printf (" %s\n", "-p"); 2148 printf(" %s\n", "-p");
2078 printf (" %s", _("number of packets to send (currently ")); 2149 printf(" %s", _("number of packets to send (currently "));
2079 printf ("%u)\n",packets); 2150 printf("%u)\n", packets);
2080 printf (" %s\n", "-i"); 2151 printf(" %s\n", "-i");
2081 printf (" %s", _("max packet interval (currently ")); 2152 printf(" %s", _("max packet interval (currently "));
2082 printf ("%0.3fms)\n",(float)pkt_interval / 1000); 2153 printf("%0.3fms)\n", (float)pkt_interval / 1000);
2083 printf (" %s\n", "-I"); 2154 printf(" %s\n", "-I");
2084 printf (" %s", _("max target interval (currently ")); 2155 printf(" %s", _("max target interval (currently "));
2085 printf ("%0.3fms)\n", (float)target_interval / 1000); 2156 printf("%0.3fms)\n", (float)target_interval / 1000);
2086 printf (" %s\n", "-m"); 2157 printf(" %s\n", "-m");
2087 printf (" %s",_("number of alive hosts required for success")); 2158 printf(" %s", _("number of alive hosts required for success"));
2088 printf ("\n"); 2159 printf("\n");
2089 printf (" %s\n", "-l"); 2160 printf(" %s\n", "-l");
2090 printf (" %s", _("TTL on outgoing packets (currently ")); 2161 printf(" %s", _("TTL on outgoing packets (currently "));
2091 printf ("%u)\n", ttl); 2162 printf("%u)\n", ttl);
2092 printf (" %s\n", "-t"); 2163 printf(" %s\n", "-t");
2093 printf (" %s",_("timeout value (seconds, currently ")); 2164 printf(" %s", _("timeout value (seconds, currently "));
2094 printf ("%u)\n", timeout); 2165 printf("%u)\n", timeout);
2095 printf (" %s\n", "-b"); 2166 printf(" %s\n", "-b");
2096 printf (" %s\n", _("Number of icmp data bytes to send")); 2167 printf(" %s\n", _("Number of icmp data bytes to send"));
2097 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); 2168 printf(" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"), icmp_data_size, ICMP_MINLEN);
2098 printf (" %s\n", "-v"); 2169 printf(" %s\n", "-v");
2099 printf (" %s\n", _("verbose")); 2170 printf(" %s\n", _("verbose"));
2100 printf ("\n"); 2171 printf("\n");
2101 printf ("%s\n", _("Notes:")); 2172 printf("%s\n", _("Notes:"));
2102 printf (" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P")); 2173 printf(" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P"));
2103 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); 2174 printf(" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
2104 printf ("\n"); 2175 printf("\n");
2105 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); 2176 printf(" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
2106 printf (" %s\n", _("packet loss. The default values should work well for most users.")); 2177 printf(" %s\n", _("packet loss. The default values should work well for most users."));
2107 printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations")); 2178 printf(" %s\n", _("You can specify different RTA factors using the standardized abbreviations"));
2108 printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); 2179 printf(" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds."));
2109 /* -d not yet implemented */ 2180 /* -d not yet implemented */
2110 /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops")); 2181 /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops"));
2111 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); 2182 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent."));
2112 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/ 2183 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/
2113 printf ("\n"); 2184 printf("\n");
2114 printf (" %s\n", _("The -v switch can be specified several times for increased verbosity.")); 2185 printf(" %s\n", _("The -v switch can be specified several times for increased verbosity."));
2115 /* printf ("%s\n", _("Long options are currently unsupported.")); 2186 /* printf ("%s\n", _("Long options are currently unsupported."));
2116 printf ("%s\n", _("Options marked with * require an argument")); 2187 printf ("%s\n", _("Options marked with * require an argument"));
2117 */ 2188 */
2118 2189
2119 printf (UT_SUPPORT); 2190 printf(UT_SUPPORT);
2120} 2191}
2121 2192
2122 2193void print_usage(void) {
2123 2194 printf("%s\n", _("Usage:"));
2124void
2125print_usage (void)
2126{
2127 printf ("%s\n", _("Usage:"));
2128 printf(" %s [options] [-H] host1 host2 hostN\n", progname); 2195 printf(" %s [options] [-H] host1 host2 hostN\n", progname);
2129} 2196}