summaryrefslogtreecommitdiffstats
path: root/plugins-root
diff options
context:
space:
mode:
authorJan Wagner <waja@cyconet.org>2023-10-17 11:39:37 (GMT)
committerJan Wagner <waja@cyconet.org>2023-10-17 11:39:37 (GMT)
commit2a047014385022c8dc06dad4da0428db14898689 (patch)
tree00abea46325decf0c72870ee8f9ec1472e8e5344 /plugins-root
parentf39211c26408af582121f519d89c8abf70e6d437 (diff)
parente23a75d954311b3be429a9020e4d317b89615ee7 (diff)
downloadmonitoring-plugins-2a047014385022c8dc06dad4da0428db14898689.tar.gz
Merge branch 'master' of github.com:monitoring-plugins/monitoring-plugins
Diffstat (limited to 'plugins-root')
-rw-r--r--plugins-root/check_dhcp.c738
-rw-r--r--plugins-root/check_icmp.c684
-rw-r--r--plugins-root/t/check_icmp.t58
3 files changed, 1007 insertions, 473 deletions
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index 2d22619..6b07df5 100644
--- a/plugins-root/check_dhcp.c
+++ b/plugins-root/check_dhcp.c
@@ -1,40 +1,40 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dhcp plugin 3 * Monitoring check_dhcp plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org) 6 * Copyright (c) 2001-2004 Ethan Galstad (nagios@nagios.org)
7* Copyright (c) 2001-2007 Monitoring Plugins Development Team 7 * Copyright (c) 2001-2007 Monitoring Plugins Development Team
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_dhcp plugin 11 * This file contains the check_dhcp plugin
12* 12 *
13* This plugin tests the availability of DHCP servers on a network. 13 * This plugin tests the availability of DHCP servers on a network.
14* 14 *
15* Unicast mode was originally implemented by Heiti of Boras Kommun with 15 * Unicast mode was originally implemented by Heiti of Boras Kommun with
16* general improvements as well as usability fixes and "forward"-porting by 16 * general improvements as well as usability fixes and "forward"-porting by
17* Andreas Ericsson of OP5 AB. 17 * Andreas Ericsson of OP5 AB.
18* 18 *
19* 19 *
20* This program is free software: you can redistribute it and/or modify 20 * This program is free software: you can redistribute it and/or modify
21* it under the terms of the GNU General Public License as published by 21 * it under the terms of the GNU General Public License as published by
22* the Free Software Foundation, either version 3 of the License, or 22 * the Free Software Foundation, either version 3 of the License, or
23* (at your option) any later version. 23 * (at your option) any later version.
24* 24 *
25* This program is distributed in the hope that it will be useful, 25 * This program is distributed in the hope that it will be useful,
26* but WITHOUT ANY WARRANTY; without even the implied warranty of 26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28* GNU General Public License for more details. 28 * GNU General Public License for more details.
29* 29 *
30* You should have received a copy of the GNU General Public License 30 * You should have received a copy of the GNU General Public License
31* along with this program. If not, see <http://www.gnu.org/licenses/>. 31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32* 32 *
33* 33 *
34*****************************************************************************/ 34 *****************************************************************************/
35 35
36const char *progname = "check_dhcp"; 36const char *progname = "check_dhcp";
37const char *copyright = "2001-2007"; 37const char *copyright = "2001-2023";
38const char *email = "devel@monitoring-plugins.org"; 38const char *email = "devel@monitoring-plugins.org";
39 39
40#include "common.h" 40#include "common.h"
@@ -57,9 +57,10 @@ const char *email = "devel@monitoring-plugins.org";
57#include <netinet/in.h> 57#include <netinet/in.h>
58#include <net/if.h> 58#include <net/if.h>
59#include <arpa/inet.h> 59#include <arpa/inet.h>
60
60#if HAVE_SYS_SOCKIO_H 61#if HAVE_SYS_SOCKIO_H
61#include <sys/sockio.h> 62#include <sys/sockio.h>
62#endif 63#endif // HAVE_SYS_SOCKIO_H
63 64
64#if defined( __linux__ ) 65#if defined( __linux__ )
65 66
@@ -98,10 +99,6 @@ static struct strbuf dat = {AREA_SZ, 0, (char *)dat_area};
98#define GOT_INTR 4 99#define GOT_INTR 4
99#define GOT_ERR 128 100#define GOT_ERR 128
100 101
101#define u_int8_t uint8_t
102#define u_int16_t uint16_t
103#define u_int32_t uint32_t
104
105static int get_msg(int); 102static int get_msg(int);
106static int check_ctrl(int); 103static int check_ctrl(int);
107static int put_ctrl(int, int, int); 104static int put_ctrl(int, int, int);
@@ -110,7 +107,7 @@ static int dl_open(const char *, int, int *);
110static int dl_bind(int, int, u_char *); 107static int dl_bind(int, int, u_char *);
111long mac_addr_dlpi( const char *, int, u_char *); 108long mac_addr_dlpi( const char *, int, u_char *);
112 109
113#endif 110#endif // __sun__ || __solaris__ || __hpux
114 111
115 112
116 113
@@ -119,9 +116,6 @@ long mac_addr_dlpi( const char *, int, u_char *);
119#define OK 0 116#define OK 0
120#define ERROR -1 117#define ERROR -1
121 118
122#define FALSE 0
123#define TRUE 1
124
125 119
126/**** DHCP definitions ****/ 120/**** DHCP definitions ****/
127 121
@@ -132,39 +126,40 @@ long mac_addr_dlpi( const char *, int, u_char *);
132 126
133 127
134typedef struct dhcp_packet_struct{ 128typedef struct dhcp_packet_struct{
135 u_int8_t op; /* packet type */ 129 uint8_t op; /* packet type */
136 u_int8_t htype; /* type of hardware address for this machine (Ethernet, etc) */ 130 uint8_t htype; /* type of hardware address for this machine (Ethernet, etc) */
137 u_int8_t hlen; /* length of hardware address (of this machine) */ 131 uint8_t hlen; /* length of hardware address (of this machine) */
138 u_int8_t hops; /* hops */ 132 uint8_t hops; /* hops */
139 u_int32_t xid; /* random transaction id number - chosen by this machine */ 133 uint32_t xid; /* random transaction id number - chosen by this machine */
140 u_int16_t secs; /* seconds used in timing */ 134 uint16_t secs; /* seconds used in timing */
141 u_int16_t flags; /* flags */ 135 uint16_t flags; /* flags */
142 struct in_addr ciaddr; /* IP address of this machine (if we already have one) */ 136 struct in_addr ciaddr; /* IP address of this machine (if we already have one) */
143 struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */ 137 struct in_addr yiaddr; /* IP address of this machine (offered by the DHCP server) */
144 struct in_addr siaddr; /* IP address of next server */ 138 struct in_addr siaddr; /* IP address of next server */
145 struct in_addr giaddr; /* IP address of DHCP relay */ 139 struct in_addr giaddr; /* IP address of DHCP relay */
146 unsigned char chaddr [MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */ 140 unsigned char chaddr [MAX_DHCP_CHADDR_LENGTH]; /* hardware address of this machine */
147 char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */ 141 char sname [MAX_DHCP_SNAME_LENGTH]; /* name of DHCP server */
148 char file [MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */ 142 char file [MAX_DHCP_FILE_LENGTH]; /* boot file name (used for diskless booting?) */
149 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */ 143 char options[MAX_DHCP_OPTIONS_LENGTH]; /* options */
150 }dhcp_packet; 144}dhcp_packet;
151 145
152 146
153typedef struct dhcp_offer_struct{ 147typedef struct dhcp_offer_struct{
154 struct in_addr server_address; /* address of DHCP server that sent this offer */ 148 struct in_addr server_address; /* address of DHCP server that sent this offer */
155 struct in_addr offered_address; /* the IP address that was offered to us */ 149 struct in_addr offered_address; /* the IP address that was offered to us */
156 u_int32_t lease_time; /* lease time in seconds */ 150 uint32_t lease_time; /* lease time in seconds */
157 u_int32_t renewal_time; /* renewal time in seconds */ 151 uint32_t renewal_time; /* renewal time in seconds */
158 u_int32_t rebinding_time; /* rebinding time in seconds */ 152 uint32_t rebinding_time; /* rebinding time in seconds */
153 bool desired; /* is this offer desired (necessary in exclusive mode) */
159 struct dhcp_offer_struct *next; 154 struct dhcp_offer_struct *next;
160 }dhcp_offer; 155}dhcp_offer;
161 156
162 157
163typedef struct requested_server_struct{ 158typedef struct requested_server_struct{
164 struct in_addr server_address; 159 struct in_addr server_address;
165 int answered; 160 bool answered;
166 struct requested_server_struct *next; 161 struct requested_server_struct *next;
167 }requested_server; 162}requested_server;
168 163
169 164
170#define BOOTREQUEST 1 165#define BOOTREQUEST 1
@@ -198,7 +193,8 @@ typedef struct requested_server_struct{
198#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */ 193#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
199#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */ 194#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
200 195
201u_int8_t unicast = 0; /* unicast mode: mimic a DHCP relay */ 196bool unicast = false; /* unicast mode: mimic a DHCP relay */
197bool exclusive = false; /* exclusive mode aka "rogue DHCP server detection" */
202struct in_addr my_ip; /* our address (required for relay) */ 198struct in_addr my_ip; /* our address (required for relay) */
203struct in_addr dhcp_ip; /* server to query (if in unicast mode) */ 199struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
204unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]=""; 200unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]="";
@@ -206,11 +202,11 @@ unsigned char *user_specified_mac=NULL;
206 202
207char network_interface_name[IFNAMSIZ]="eth0"; 203char network_interface_name[IFNAMSIZ]="eth0";
208 204
209u_int32_t packet_xid=0; 205uint32_t packet_xid=0;
210 206
211u_int32_t dhcp_lease_time=0; 207uint32_t dhcp_lease_time=0;
212u_int32_t dhcp_renewal_time=0; 208uint32_t dhcp_renewal_time=0;
213u_int32_t dhcp_rebinding_time=0; 209uint32_t dhcp_rebinding_time=0;
214 210
215int dhcpoffer_timeout=2; 211int dhcpoffer_timeout=2;
216 212
@@ -221,8 +217,8 @@ int valid_responses=0; /* number of valid DHCPOFFERs we received */
221int requested_servers=0; 217int requested_servers=0;
222int requested_responses=0; 218int requested_responses=0;
223 219
224int request_specific_address=FALSE; 220bool request_specific_address=false;
225int received_requested_address=FALSE; 221bool received_requested_address=false;
226int verbose=0; 222int verbose=0;
227struct in_addr requested_address; 223struct in_addr requested_address;
228 224
@@ -268,7 +264,7 @@ int main(int argc, char **argv){
268 264
269 if(process_arguments(argc,argv)!=OK){ 265 if(process_arguments(argc,argv)!=OK){
270 usage4 (_("Could not parse arguments")); 266 usage4 (_("Could not parse arguments"));
271 } 267 }
272 268
273 /* create socket for DHCP communications */ 269 /* create socket for DHCP communications */
274 dhcp_socket=create_dhcp_socket(); 270 dhcp_socket=create_dhcp_socket();
@@ -299,7 +295,7 @@ int main(int argc, char **argv){
299 free_requested_server_list(); 295 free_requested_server_list();
300 296
301 return result; 297 return result;
302 } 298}
303 299
304 300
305 301
@@ -314,83 +310,83 @@ int get_hardware_address(int sock,char *interface_name){
314 310
315 /* try and grab hardware address of requested interface */ 311 /* try and grab hardware address of requested interface */
316 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){ 312 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){
317 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name); 313 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name);
318 exit(STATE_UNKNOWN); 314 exit(STATE_UNKNOWN);
319 } 315 }
320 316
321 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6); 317 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6);
322 318
323#elif defined(__bsd__) 319#elif defined(__bsd__)
324 /* King 2004 see ACKNOWLEDGEMENTS */ 320 /* King 2004 see ACKNOWLEDGEMENTS */
325 321
326 size_t len; 322 size_t len;
327 int mib[6]; 323 int mib[6];
328 char *buf; 324 char *buf;
329 unsigned char *ptr; 325 unsigned char *ptr;
330 struct if_msghdr *ifm; 326 struct if_msghdr *ifm;
331 struct sockaddr_dl *sdl; 327 struct sockaddr_dl *sdl;
332 328
333 mib[0] = CTL_NET; 329 mib[0] = CTL_NET;
334 mib[1] = AF_ROUTE; 330 mib[1] = AF_ROUTE;
335 mib[2] = 0; 331 mib[2] = 0;
336 mib[3] = AF_LINK; 332 mib[3] = AF_LINK;
337 mib[4] = NET_RT_IFLIST; 333 mib[4] = NET_RT_IFLIST;
338 334
339 if((mib[5] = if_nametoindex(interface_name)) == 0){ 335 if((mib[5] = if_nametoindex(interface_name)) == 0){
340 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno)); 336 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno));
341 exit(STATE_UNKNOWN); 337 exit(STATE_UNKNOWN);
342 } 338 }
343 339
344 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){ 340 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){
345 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno)); 341 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno));
346 exit(STATE_UNKNOWN); 342 exit(STATE_UNKNOWN);
347 } 343 }
348 344
349 if((buf = malloc(len)) == NULL){ 345 if((buf = malloc(len)) == NULL){
350 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno)); 346 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno));
351 exit(4); 347 exit(4);
352 } 348 }
353 349
354 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){ 350 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){
355 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno)); 351 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno));
356 exit(STATE_UNKNOWN); 352 exit(STATE_UNKNOWN);
357 } 353 }
358 354
359 ifm = (struct if_msghdr *)buf; 355 ifm = (struct if_msghdr *)buf;
360 sdl = (struct sockaddr_dl *)(ifm + 1); 356 sdl = (struct sockaddr_dl *)(ifm + 1);
361 ptr = (unsigned char *)LLADDR(sdl); 357 ptr = (unsigned char *)LLADDR(sdl);
362 memcpy(&client_hardware_address[0], ptr, 6) ; 358 memcpy(&client_hardware_address[0], ptr, 6) ;
363 /* King 2004 */ 359 /* King 2004 */
364 360
365#elif defined(__sun__) || defined(__solaris__) 361#elif defined(__sun__) || defined(__solaris__)
366 362
367 /* Kompf 2000-2003 see ACKNOWLEDGEMENTS */ 363 /* Kompf 2000-2003 see ACKNOWLEDGEMENTS */
368 long stat; 364 long stat;
369 char dev[20] = "/dev/"; 365 char dev[20] = "/dev/";
370 char *p; 366 char *p;
371 int unit; 367 int unit;
372 368
373 /* get last number from interfacename, eg lnc0, e1000g0*/ 369 /* get last number from interfacename, eg lnc0, e1000g0*/
374 int i; 370 int i;
375 p = interface_name + strlen(interface_name) -1; 371 p = interface_name + strlen(interface_name) -1;
376 for(i = strlen(interface_name) -1; i > 0; p--) { 372 for(i = strlen(interface_name) -1; i > 0; p--) {
377 if(isalpha(*p)) 373 if(isalpha(*p))
378 break; 374 break;
379 } 375 }
380 p++; 376 p++;
381 if( p != interface_name ){ 377 if( p != interface_name ){
382 unit = atoi(p) ; 378 unit = atoi(p) ;
383 strncat(dev, interface_name, 6) ; 379 strncat(dev, interface_name, 6) ;
384 } 380 }
385 else{ 381 else{
386 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name); 382 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name);
387 exit(STATE_UNKNOWN); 383 exit(STATE_UNKNOWN);
388 } 384 }
389 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 385 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
390 if(stat != 0){ 386 if(stat != 0){
391 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 387 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
392 exit(STATE_UNKNOWN); 388 exit(STATE_UNKNOWN);
393 } 389 }
394 390
395#elif defined(__hpux__) 391#elif defined(__hpux__)
396 392
@@ -402,8 +398,8 @@ int get_hardware_address(int sock,char *interface_name){
402 if(stat != 0){ 398 if(stat != 0){
403 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 399 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
404 exit(STATE_UNKNOWN); 400 exit(STATE_UNKNOWN);
405 } 401 }
406 /* Kompf 2000-2003 */ 402 /* Kompf 2000-2003 */
407 403
408#else 404#else
409 printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n")); 405 printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n"));
@@ -414,7 +410,7 @@ int get_hardware_address(int sock,char *interface_name){
414 print_hardware_address(client_hardware_address); 410 print_hardware_address(client_hardware_address);
415 411
416 return OK; 412 return OK;
417 } 413}
418 414
419/* determines IP address of the client interface */ 415/* determines IP address of the client interface */
420int get_ip_address(int sock,char *interface_name){ 416int get_ip_address(int sock,char *interface_name){
@@ -426,9 +422,9 @@ int get_ip_address(int sock,char *interface_name){
426 422
427 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){ 423 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){
428 printf(_("Error: Cannot determine IP address of interface %s\n"), 424 printf(_("Error: Cannot determine IP address of interface %s\n"),
429 interface_name); 425 interface_name);
430 exit(STATE_UNKNOWN); 426 exit(STATE_UNKNOWN);
431 } 427 }
432 428
433 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 429 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
434 430
@@ -441,13 +437,13 @@ int get_ip_address(int sock,char *interface_name){
441 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip)); 437 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip));
442 438
443 return OK; 439 return OK;
444 } 440}
445 441
446/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ 442/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
447int send_dhcp_discover(int sock){ 443int send_dhcp_discover(int sock){
448 dhcp_packet discover_packet; 444 dhcp_packet discover_packet;
449 struct sockaddr_in sockaddr_broadcast; 445 struct sockaddr_in sockaddr_broadcast;
450 unsigned short opts; 446 unsigned short opts;
451 447
452 448
453 /* clear the packet data structure */ 449 /* clear the packet data structure */
@@ -488,19 +484,19 @@ int send_dhcp_discover(int sock){
488 discover_packet.options[2]='\x53'; 484 discover_packet.options[2]='\x53';
489 discover_packet.options[3]='\x63'; 485 discover_packet.options[3]='\x63';
490 486
491 opts = 4; 487 opts = 4;
492 /* DHCP message type is embedded in options field */ 488 /* DHCP message type is embedded in options field */
493 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ 489 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
494 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */ 490 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */
495 discover_packet.options[opts++]=DHCPDISCOVER; 491 discover_packet.options[opts++]=DHCPDISCOVER;
496 492
497 /* the IP address we're requesting */ 493 /* the IP address we're requesting */
498 if(request_specific_address==TRUE){ 494 if(request_specific_address){
499 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS; 495 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS;
500 discover_packet.options[opts++]='\x04'; 496 discover_packet.options[opts++]='\x04';
501 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address)); 497 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address));
502 opts += sizeof(requested_address); 498 opts += sizeof(requested_address);
503 } 499 }
504 discover_packet.options[opts++]=DHCP_OPTION_END; 500 discover_packet.options[opts++]=DHCP_OPTION_END;
505 501
506 /* unicast fields */ 502 /* unicast fields */
@@ -511,8 +507,8 @@ int send_dhcp_discover(int sock){
511 discover_packet.hops = unicast ? 1 : 0; 507 discover_packet.hops = unicast ? 1 : 0;
512 508
513 /* send the DHCPDISCOVER packet to broadcast address */ 509 /* send the DHCPDISCOVER packet to broadcast address */
514 sockaddr_broadcast.sin_family=AF_INET; 510 sockaddr_broadcast.sin_family=AF_INET;
515 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); 511 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT);
516 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; 512 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST;
517 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); 513 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero));
518 514
@@ -524,7 +520,7 @@ int send_dhcp_discover(int sock){
524 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); 520 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr));
525 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); 521 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr));
526 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); 522 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr));
527 } 523 }
528 524
529 /* send the DHCPDISCOVER packet out */ 525 /* send the DHCPDISCOVER packet out */
530 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); 526 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast);
@@ -533,7 +529,7 @@ int send_dhcp_discover(int sock){
533 printf("\n\n"); 529 printf("\n\n");
534 530
535 return OK; 531 return OK;
536 } 532}
537 533
538 534
539 535
@@ -573,13 +569,13 @@ int get_dhcp_offer(int sock){
573 printf(_("Result=ERROR\n")); 569 printf(_("Result=ERROR\n"));
574 570
575 continue; 571 continue;
576 } 572 }
577 else{ 573 else{
578 if(verbose) 574 if(verbose)
579 printf(_("Result=OK\n")); 575 printf(_("Result=OK\n"));
580 576
581 responses++; 577 responses++;
582 } 578 }
583 579
584 /* The "source" is either a server or a relay. */ 580 /* The "source" is either a server or a relay. */
585 /* Save a copy of "source" into "via" even if it's via itself */ 581 /* Save a copy of "source" into "via" even if it's via itself */
@@ -589,7 +585,7 @@ int get_dhcp_offer(int sock){
589 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr)); 585 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr));
590 printf(_(" via %s\n"),inet_ntoa(via.sin_addr)); 586 printf(_(" via %s\n"),inet_ntoa(via.sin_addr));
591 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid)); 587 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid));
592 } 588 }
593 589
594 /* check packet xid to see if its the same as the one we used in the discover packet */ 590 /* check packet xid to see if its the same as the one we used in the discover packet */
595 if(ntohl(offer_packet.xid)!=packet_xid){ 591 if(ntohl(offer_packet.xid)!=packet_xid){
@@ -597,7 +593,7 @@ int get_dhcp_offer(int sock){
597 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid); 593 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid);
598 594
599 continue; 595 continue;
600 } 596 }
601 597
602 /* check hardware address */ 598 /* check hardware address */
603 result=OK; 599 result=OK;
@@ -610,7 +606,7 @@ int get_dhcp_offer(int sock){
610 606
611 if(offer_packet.chaddr[x]!=client_hardware_address[x]) 607 if(offer_packet.chaddr[x]!=client_hardware_address[x])
612 result=ERROR; 608 result=ERROR;
613 } 609 }
614 if(verbose) 610 if(verbose)
615 printf("\n"); 611 printf("\n");
616 612
@@ -619,27 +615,27 @@ int get_dhcp_offer(int sock){
619 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); 615 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n"));
620 616
621 continue; 617 continue;
622 } 618 }
623 619
624 if(verbose){ 620 if(verbose){
625 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); 621 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr));
626 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr)); 622 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr));
627 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr)); 623 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr));
628 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr)); 624 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr));
629 } 625 }
630 626
631 add_dhcp_offer(source.sin_addr,&offer_packet); 627 add_dhcp_offer(source.sin_addr,&offer_packet);
632 628
633 valid_responses++; 629 valid_responses++;
634 } 630 }
635 631
636 if(verbose){ 632 if(verbose){
637 printf(_("Total responses seen on the wire: %d\n"),responses); 633 printf(_("Total responses seen on the wire: %d\n"),responses);
638 printf(_("Valid responses for this machine: %d\n"),valid_responses); 634 printf(_("Valid responses for this machine: %d\n"),valid_responses);
639 } 635 }
640 636
641 return OK; 637 return OK;
642 } 638}
643 639
644 640
645 641
@@ -656,14 +652,14 @@ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in
656 return ERROR; 652 return ERROR;
657 653
658 return OK; 654 return OK;
659 } 655}
660 656
661 657
662 658
663/* receives a DHCP packet */ 659/* receives a DHCP packet */
664int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){ 660int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){
665 struct timeval tv; 661 struct timeval tv;
666 fd_set readfds; 662 fd_set readfds;
667 fd_set oobfds; 663 fd_set oobfds;
668 int recv_result; 664 int recv_result;
669 socklen_t address_size; 665 socklen_t address_size;
@@ -671,88 +667,88 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st
671 int nfound; 667 int nfound;
672 668
673 669
674 /* wait for data to arrive (up time timeout) */ 670 /* wait for data to arrive (up time timeout) */
675 tv.tv_sec=timeout; 671 tv.tv_sec=timeout;
676 tv.tv_usec=0; 672 tv.tv_usec=0;
677 FD_ZERO(&readfds); 673 FD_ZERO(&readfds);
678 FD_ZERO(&oobfds); 674 FD_ZERO(&oobfds);
679 FD_SET(sock,&readfds); 675 FD_SET(sock,&readfds);
680 FD_SET(sock,&oobfds); 676 FD_SET(sock,&oobfds);
681 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv); 677 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv);
682 678
683 /* make sure some data has arrived */ 679 /* make sure some data has arrived */
684 if(!FD_ISSET(sock,&readfds)){ 680 if(!FD_ISSET(sock,&readfds)){
685 if(verbose) 681 if(verbose)
686 printf(_("No (more) data received (nfound: %d)\n"), nfound); 682 printf(_("No (more) data received (nfound: %d)\n"), nfound);
687 return ERROR; 683 return ERROR;
688 } 684 }
689 685
690 else{ 686 else{
691 bzero(&source_address,sizeof(source_address)); 687 bzero(&source_address,sizeof(source_address));
692 address_size=sizeof(source_address); 688 address_size=sizeof(source_address);
693 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size); 689 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size);
694 if(verbose) 690 if(verbose)
695 printf("recv_result: %d\n",recv_result); 691 printf("recv_result: %d\n",recv_result);
696 692
697 if(recv_result==-1){ 693 if(recv_result==-1){
698 if(verbose){ 694 if(verbose){
699 printf(_("recvfrom() failed, ")); 695 printf(_("recvfrom() failed, "));
700 printf("errno: (%d) -> %s\n",errno,strerror(errno)); 696 printf("errno: (%d) -> %s\n",errno,strerror(errno));
701 } 697 }
702 return ERROR; 698 return ERROR;
703 } 699 }
704 else{ 700 else{
705 if(verbose){ 701 if(verbose){
706 printf(_("receive_dhcp_packet() result: %d\n"),recv_result); 702 printf(_("receive_dhcp_packet() result: %d\n"),recv_result);
707 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr)); 703 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr));
708 } 704 }
709 705
710 memcpy(address,&source_address,sizeof(source_address)); 706 memcpy(address,&source_address,sizeof(source_address));
711 return OK; 707 return OK;
712 } 708 }
713 } 709 }
714 710
715 return OK; 711 return OK;
716 } 712}
717 713
718 714
719/* creates a socket for DHCP communication */ 715/* creates a socket for DHCP communication */
720int create_dhcp_socket(void){ 716int create_dhcp_socket(void){
721 struct sockaddr_in myname; 717 struct sockaddr_in myname;
722 struct ifreq interface; 718 struct ifreq interface;
723 int sock; 719 int sock;
724 int flag=1; 720 int flag=1;
725 721
726 /* Set up the address we're going to bind to. */ 722 /* Set up the address we're going to bind to. */
727 bzero(&myname,sizeof(myname)); 723 bzero(&myname,sizeof(myname));
728 myname.sin_family=AF_INET; 724 myname.sin_family=AF_INET;
729 /* listen to DHCP server port if we're in unicast mode */ 725 /* listen to DHCP server port if we're in unicast mode */
730 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT); 726 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT);
731 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY; 727 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY;
732 bzero(&myname.sin_zero,sizeof(myname.sin_zero)); 728 bzero(&myname.sin_zero,sizeof(myname.sin_zero));
733 729
734 /* create a socket for DHCP communications */ 730 /* create a socket for DHCP communications */
735 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 731 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
736 if(sock<0){ 732 if(sock<0){
737 printf(_("Error: Could not create socket!\n")); 733 printf(_("Error: Could not create socket!\n"));
738 exit(STATE_UNKNOWN); 734 exit(STATE_UNKNOWN);
739 } 735 }
740 736
741 if(verbose) 737 if(verbose)
742 printf("DHCP socket: %d\n",sock); 738 printf("DHCP socket: %d\n",sock);
743 739
744 /* set the reuse address flag so we don't get errors when restarting */ 740 /* set the reuse address flag so we don't get errors when restarting */
745 flag=1; 741 flag=1;
746 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ 742 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
747 printf(_("Error: Could not set reuse address option on DHCP socket!\n")); 743 printf(_("Error: Could not set reuse address option on DHCP socket!\n"));
748 exit(STATE_UNKNOWN); 744 exit(STATE_UNKNOWN);
749 } 745 }
750 746
751 /* set the broadcast option - we need this to listen to DHCP broadcast messages */ 747 /* set the broadcast option - we need this to listen to DHCP broadcast messages */
752 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ 748 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){
753 printf(_("Error: Could not set broadcast option on DHCP socket!\n")); 749 printf(_("Error: Could not set broadcast option on DHCP socket!\n"));
754 exit(STATE_UNKNOWN); 750 exit(STATE_UNKNOWN);
755 } 751 }
756 752
757 /* bind socket to interface */ 753 /* bind socket to interface */
758#if defined(__linux__) 754#if defined(__linux__)
@@ -761,21 +757,21 @@ int create_dhcp_socket(void){
761 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){ 757 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){
762 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name); 758 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name);
763 exit(STATE_UNKNOWN); 759 exit(STATE_UNKNOWN);
764 } 760 }
765 761
766#else 762#else
767 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1); 763 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1);
768 interface.ifr_name[IFNAMSIZ-1]='\0'; 764 interface.ifr_name[IFNAMSIZ-1]='\0';
769#endif 765#endif
770 766
771 /* bind the socket */ 767 /* bind the socket */
772 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ 768 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
773 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT); 769 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT);
774 exit(STATE_UNKNOWN); 770 exit(STATE_UNKNOWN);
775 } 771 }
776 772
777 return sock; 773 return sock;
778 } 774}
779 775
780 776
781/* closes DHCP socket */ 777/* closes DHCP socket */
@@ -784,7 +780,7 @@ int close_dhcp_socket(int sock){
784 close(sock); 780 close(sock);
785 781
786 return OK; 782 return OK;
787 } 783}
788 784
789 785
790/* adds a requested server address to list in memory */ 786/* adds a requested server address to list in memory */
@@ -796,7 +792,7 @@ int add_requested_server(struct in_addr server_address){
796 return ERROR; 792 return ERROR;
797 793
798 new_server->server_address=server_address; 794 new_server->server_address=server_address;
799 new_server->answered=FALSE; 795 new_server->answered=false;
800 796
801 new_server->next=requested_server_list; 797 new_server->next=requested_server_list;
802 requested_server_list=new_server; 798 requested_server_list=new_server;
@@ -807,7 +803,7 @@ int add_requested_server(struct in_addr server_address){
807 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address)); 803 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address));
808 804
809 return OK; 805 return OK;
810 } 806}
811 807
812 808
813 809
@@ -840,29 +836,29 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
840 836
841 /* get option data */ 837 /* get option data */
842 switch(option_type){ 838 switch(option_type){
843 case DHCP_OPTION_LEASE_TIME: 839 case DHCP_OPTION_LEASE_TIME:
844 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time)); 840 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time));
845 dhcp_lease_time = ntohl(dhcp_lease_time); 841 dhcp_lease_time = ntohl(dhcp_lease_time);
846 break; 842 break;
847 case DHCP_OPTION_RENEWAL_TIME: 843 case DHCP_OPTION_RENEWAL_TIME:
848 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time)); 844 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time));
849 dhcp_renewal_time = ntohl(dhcp_renewal_time); 845 dhcp_renewal_time = ntohl(dhcp_renewal_time);
850 break; 846 break;
851 case DHCP_OPTION_REBINDING_TIME: 847 case DHCP_OPTION_REBINDING_TIME:
852 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time)); 848 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time));
853 dhcp_rebinding_time = ntohl(dhcp_rebinding_time); 849 dhcp_rebinding_time = ntohl(dhcp_rebinding_time);
854 break; 850 break;
855 case DHCP_OPTION_SERVER_IDENTIFIER: 851 case DHCP_OPTION_SERVER_IDENTIFIER:
856 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr)); 852 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr));
857 break; 853 break;
858 } 854 }
859 855
860 /* skip option data we're ignoring */ 856 /* skip option data we're ignoring */
861 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */ 857 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */
862 x+=1; 858 x+=1;
863 else 859 else
864 x+=option_length; 860 x+=option_length;
865 } 861 }
866 862
867 if(verbose){ 863 if(verbose){
868 if(dhcp_lease_time==DHCP_INFINITE_TIME) 864 if(dhcp_lease_time==DHCP_INFINITE_TIME)
@@ -876,7 +872,7 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
876 if(dhcp_rebinding_time==DHCP_INFINITE_TIME) 872 if(dhcp_rebinding_time==DHCP_INFINITE_TIME)
877 printf(_("Rebinding Time: Infinite\n")); 873 printf(_("Rebinding Time: Infinite\n"));
878 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time); 874 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time);
879 } 875 }
880 876
881 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer)); 877 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer));
882 878
@@ -900,19 +896,20 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
900 new_offer->lease_time=dhcp_lease_time; 896 new_offer->lease_time=dhcp_lease_time;
901 new_offer->renewal_time=dhcp_renewal_time; 897 new_offer->renewal_time=dhcp_renewal_time;
902 new_offer->rebinding_time=dhcp_rebinding_time; 898 new_offer->rebinding_time=dhcp_rebinding_time;
899 new_offer->desired=false; /* exclusive mode: we'll check that in get_results */
903 900
904 901
905 if(verbose){ 902 if(verbose){
906 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address)); 903 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address));
907 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address)); 904 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address));
908 } 905 }
909 906
910 /* add new offer to head of list */ 907 /* add new offer to head of list */
911 new_offer->next=dhcp_offer_list; 908 new_offer->next=dhcp_offer_list;
912 dhcp_offer_list=new_offer; 909 dhcp_offer_list=new_offer;
913 910
914 return OK; 911 return OK;
915 } 912}
916 913
917 914
918/* frees memory allocated to DHCP OFFER list */ 915/* frees memory allocated to DHCP OFFER list */
@@ -923,10 +920,10 @@ int free_dhcp_offer_list(void){
923 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){ 920 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){
924 next_offer=this_offer->next; 921 next_offer=this_offer->next;
925 free(this_offer); 922 free(this_offer);
926 } 923 }
927 924
928 return OK; 925 return OK;
929 } 926}
930 927
931 928
932/* frees memory allocated to requested server list */ 929/* frees memory allocated to requested server list */
@@ -937,20 +934,20 @@ int free_requested_server_list(void){
937 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){ 934 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){
938 next_server=this_server->next; 935 next_server=this_server->next;
939 free(this_server); 936 free(this_server);
940 } 937 }
941 938
942 return OK; 939 return OK;
943 } 940}
944 941
945 942
946/* gets state and plugin output to return */ 943/* gets state and plugin output to return */
947int get_results(void){ 944int get_results(void){
948 dhcp_offer *temp_offer; 945 dhcp_offer *temp_offer, *undesired_offer=NULL;
949 requested_server *temp_server; 946 requested_server *temp_server;
950 int result; 947 int result;
951 u_int32_t max_lease_time=0; 948 uint32_t max_lease_time=0;
952 949
953 received_requested_address=FALSE; 950 received_requested_address=false;
954 951
955 /* checks responses from requested servers */ 952 /* checks responses from requested servers */
956 requested_responses=0; 953 requested_responses=0;
@@ -966,7 +963,7 @@ int get_results(void){
966 963
967 /* see if we got the address we requested */ 964 /* see if we got the address we requested */
968 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 965 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
969 received_requested_address=TRUE; 966 received_requested_address=true;
970 967
971 /* see if the servers we wanted a response from talked to us or not */ 968 /* see if the servers we wanted a response from talked to us or not */
972 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){ 969 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){
@@ -976,16 +973,24 @@ int get_results(void){
976 if(temp_server->answered) 973 if(temp_server->answered)
977 printf(_(" (duplicate)")); 974 printf(_(" (duplicate)"));
978 printf(_("\n")); 975 printf(_("\n"));
979 } 976 }
980 if(temp_server->answered == FALSE){ 977 if(!temp_server->answered){
981 requested_responses++; 978 requested_responses++;
982 temp_server->answered=TRUE; 979 temp_server->answered=true;
983 } 980 temp_offer->desired=true;
984 } 981 }
985 } 982 }
986 } 983 }
984 }
987 985
988 } 986 /* exclusive mode: check for undesired offers */
987 for(temp_offer=dhcp_offer_list;temp_offer!=NULL;temp_offer=temp_offer->next) {
988 if (!temp_offer->desired) {
989 undesired_offer=temp_offer; /* Checks only for the first undesired offer */
990 break; /* no further checks needed */
991 }
992 }
993 }
989 994
990 /* else check and see if we got our requested address from any server */ 995 /* else check and see if we got our requested address from any server */
991 else{ 996 else{
@@ -998,9 +1003,9 @@ int get_results(void){
998 1003
999 /* see if we got the address we requested */ 1004 /* see if we got the address we requested */
1000 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 1005 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
1001 received_requested_address=TRUE; 1006 received_requested_address=true;
1002 } 1007 }
1003 } 1008 }
1004 1009
1005 result=STATE_OK; 1010 result=STATE_OK;
1006 if(valid_responses==0) 1011 if(valid_responses==0)
@@ -1009,9 +1014,12 @@ int get_results(void){
1009 result=STATE_CRITICAL; 1014 result=STATE_CRITICAL;
1010 else if(requested_responses<requested_servers) 1015 else if(requested_responses<requested_servers)
1011 result=STATE_WARNING; 1016 result=STATE_WARNING;
1012 else if(request_specific_address==TRUE && received_requested_address==FALSE) 1017 else if(request_specific_address && !received_requested_address)
1013 result=STATE_WARNING; 1018 result=STATE_WARNING;
1014 1019
1020 if(exclusive && undesired_offer)
1021 result=STATE_CRITICAL;
1022
1015 if(result==0) /* garrett honeycutt 2005 */ 1023 if(result==0) /* garrett honeycutt 2005 */
1016 printf("OK: "); 1024 printf("OK: ");
1017 else if(result==1) 1025 else if(result==1)
@@ -1025,15 +1033,22 @@ int get_results(void){
1025 if(dhcp_offer_list==NULL){ 1033 if(dhcp_offer_list==NULL){
1026 printf(_("No DHCPOFFERs were received.\n")); 1034 printf(_("No DHCPOFFERs were received.\n"));
1027 return result; 1035 return result;
1028 } 1036 }
1029 1037
1030 printf(_("Received %d DHCPOFFER(s)"),valid_responses); 1038 printf(_("Received %d DHCPOFFER(s)"),valid_responses);
1031 1039
1040
1041 if(exclusive && undesired_offer){
1042 printf(_(", Rogue DHCP Server detected! Server %s"),inet_ntoa(undesired_offer->server_address));
1043 printf(_(" offered %s \n"),inet_ntoa(undesired_offer->offered_address));
1044 return result;
1045 }
1046
1032 if(requested_servers>0) 1047 if(requested_servers>0)
1033 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers); 1048 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers);
1034 1049
1035 if(request_specific_address==TRUE) 1050 if(request_specific_address)
1036 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address==TRUE)?"":_("not ")); 1051 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address)?"":_("not "));
1037 1052
1038 printf(_(", max lease time = ")); 1053 printf(_(", max lease time = "));
1039 if(max_lease_time==DHCP_INFINITE_TIME) 1054 if(max_lease_time==DHCP_INFINITE_TIME)
@@ -1044,17 +1059,15 @@ int get_results(void){
1044 printf(".\n"); 1059 printf(".\n");
1045 1060
1046 return result; 1061 return result;
1047 } 1062}
1048 1063
1049 1064
1050/* process command-line arguments */ 1065/* process command-line arguments */
1051int process_arguments(int argc, char **argv){ 1066int process_arguments(int argc, char **argv){
1052 int arg_index;
1053
1054 if(argc<1) 1067 if(argc<1)
1055 return ERROR; 1068 return ERROR;
1056 1069
1057 arg_index = call_getopt(argc,argv); 1070 call_getopt(argc,argv);
1058 return validate_arguments(argc); 1071 return validate_arguments(argc);
1059} 1072}
1060 1073
@@ -1071,87 +1084,89 @@ int call_getopt(int argc, char **argv){
1071 {"interface", required_argument,0,'i'}, 1084 {"interface", required_argument,0,'i'},
1072 {"mac", required_argument,0,'m'}, 1085 {"mac", required_argument,0,'m'},
1073 {"unicast", no_argument, 0,'u'}, 1086 {"unicast", no_argument, 0,'u'},
1087 {"exclusive", no_argument, 0,'x'},
1074 {"verbose", no_argument, 0,'v'}, 1088 {"verbose", no_argument, 0,'v'},
1075 {"version", no_argument, 0,'V'}, 1089 {"version", no_argument, 0,'V'},
1076 {"help", no_argument, 0,'h'}, 1090 {"help", no_argument, 0,'h'},
1077 {0,0,0,0} 1091 {0,0,0,0}
1078 }; 1092 };
1079 1093
1080 while(1){ 1094 int c=0;
1081 int c=0; 1095 while(true){
1082 1096 c=getopt_long(argc,argv,"+hVvxt:s:r:t:i:m:u",long_options,&option_index);
1083 c=getopt_long(argc,argv,"+hVvt:s:r:t:i:m:u",long_options,&option_index);
1084 1097
1085 if(c==-1||c==EOF||c==1) 1098 if(c==-1||c==EOF||c==1)
1086 break; 1099 break;
1087 1100
1088 switch(c){ 1101 switch(c){
1089 1102
1090 case 's': /* DHCP server address */ 1103 case 's': /* DHCP server address */
1091 resolve_host(optarg,&dhcp_ip); 1104 resolve_host(optarg,&dhcp_ip);
1092 add_requested_server(dhcp_ip); 1105 add_requested_server(dhcp_ip);
1093 break; 1106 break;
1094 1107
1095 case 'r': /* address we are requested from DHCP servers */ 1108 case 'r': /* address we are requested from DHCP servers */
1096 resolve_host(optarg,&requested_address); 1109 resolve_host(optarg,&requested_address);
1097 request_specific_address=TRUE; 1110 request_specific_address=true;
1098 break; 1111 break;
1099 1112
1100 case 't': /* timeout */ 1113 case 't': /* timeout */
1101 1114
1102 /* 1115 /*
1103 if(is_intnonneg(optarg)) 1116 if(is_intnonneg(optarg))
1104 */ 1117 */
1105 if(atoi(optarg)>0) 1118 if(atoi(optarg)>0)
1106 dhcpoffer_timeout=atoi(optarg); 1119 dhcpoffer_timeout=atoi(optarg);
1107 /* 1120 /*
1108 else 1121 else
1109 usage("Time interval must be a nonnegative integer\n"); 1122 usage("Time interval must be a nonnegative integer\n");
1110 */ 1123 */
1111 break; 1124 break;
1112 1125
1113 case 'm': /* MAC address */ 1126 case 'm': /* MAC address */
1114 1127
1115 if((user_specified_mac=mac_aton(optarg)) == NULL) 1128 if((user_specified_mac=mac_aton(optarg)) == NULL)
1116 usage("Cannot parse MAC address.\n"); 1129 usage("Cannot parse MAC address.\n");
1117 if(verbose) 1130 if(verbose)
1118 print_hardware_address(user_specified_mac); 1131 print_hardware_address(user_specified_mac);
1119 1132
1120 break; 1133 break;
1121 1134
1122 case 'i': /* interface name */ 1135 case 'i': /* interface name */
1123 1136
1124 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1); 1137 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1);
1125 network_interface_name[sizeof(network_interface_name)-1]='\x0'; 1138 network_interface_name[sizeof(network_interface_name)-1]='\x0';
1126 1139
1127 break; 1140 break;
1128 1141
1129 case 'u': /* unicast testing */ 1142 case 'u': /* unicast testing */
1130 unicast=1; 1143 unicast=true;
1131 break; 1144 break;
1132 1145 case 'x': /* exclusive testing aka "rogue DHCP server detection" */
1133 case 'V': /* version */ 1146 exclusive=true;
1134 print_revision(progname, NP_VERSION); 1147 break;
1135 exit(STATE_UNKNOWN); 1148
1136 1149 case 'V': /* version */
1137 case 'h': /* help */ 1150 print_revision(progname, NP_VERSION);
1138 print_help(); 1151 exit(STATE_UNKNOWN);
1139 exit(STATE_UNKNOWN); 1152
1140 1153 case 'h': /* help */
1141 case 'v': /* verbose */ 1154 print_help();
1142 verbose=1; 1155 exit(STATE_UNKNOWN);
1143 break; 1156
1144 1157 case 'v': /* verbose */
1145 case '?': /* help */ 1158 verbose=1;
1146 usage5 (); 1159 break;
1147 break; 1160 case '?': /* help */
1148 1161 usage5 ();
1149 default: 1162 break;
1150 break; 1163
1151 } 1164 default:
1152 } 1165 break;
1166 }
1167 }
1153 return optind; 1168 return optind;
1154 } 1169}
1155 1170
1156 1171
1157int validate_arguments(int argc){ 1172int validate_arguments(int argc){
@@ -1178,21 +1193,21 @@ static int get_msg(int fd){
1178 if(res < 0){ 1193 if(res < 0){
1179 if(errno == EINTR){ 1194 if(errno == EINTR){
1180 return(GOT_INTR); 1195 return(GOT_INTR);
1181 } 1196 }
1182 else{ 1197 else{
1183 printf("%s\n", "get_msg FAILED."); 1198 printf("%s\n", "get_msg FAILED.");
1184 return(GOT_ERR); 1199 return(GOT_ERR);
1185 }
1186 } 1200 }
1201 }
1187 if(ctl.len > 0){ 1202 if(ctl.len > 0){
1188 ret |= GOT_CTRL; 1203 ret |= GOT_CTRL;
1189 } 1204 }
1190 if(dat.len > 0){ 1205 if(dat.len > 0){
1191 ret |= GOT_DATA; 1206 ret |= GOT_DATA;
1192 } 1207 }
1193 1208
1194 return(ret); 1209 return(ret);
1195 } 1210}
1196 1211
1197/* verify that dl_primitive in ctl_area = prim */ 1212/* verify that dl_primitive in ctl_area = prim */
1198static int check_ctrl(int prim){ 1213static int check_ctrl(int prim){
@@ -1201,10 +1216,10 @@ static int check_ctrl(int prim){
1201 if(err_ack->dl_primitive != prim){ 1216 if(err_ack->dl_primitive != prim){
1202 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno)); 1217 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno));
1203 exit(STATE_UNKNOWN); 1218 exit(STATE_UNKNOWN);
1204 } 1219 }
1205 1220
1206 return 0; 1221 return 0;
1207 } 1222}
1208 1223
1209/* put a control message on a stream */ 1224/* put a control message on a stream */
1210static int put_ctrl(int fd, int len, int pri){ 1225static int put_ctrl(int fd, int len, int pri){
@@ -1213,10 +1228,10 @@ static int put_ctrl(int fd, int len, int pri){
1213 if(putmsg(fd, &ctl, 0, pri) < 0){ 1228 if(putmsg(fd, &ctl, 0, pri) < 0){
1214 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno)); 1229 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno));
1215 exit(STATE_UNKNOWN); 1230 exit(STATE_UNKNOWN);
1216 } 1231 }
1217 1232
1218 return 0; 1233 return 0;
1219 } 1234}
1220 1235
1221/* put a control + data message on a stream */ 1236/* put a control + data message on a stream */
1222static int put_both(int fd, int clen, int dlen, int pri){ 1237static int put_both(int fd, int clen, int dlen, int pri){
@@ -1226,10 +1241,10 @@ static int put_both(int fd, int clen, int dlen, int pri){
1226 if(putmsg(fd, &ctl, &dat, pri) < 0){ 1241 if(putmsg(fd, &ctl, &dat, pri) < 0){
1227 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno)); 1242 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno));
1228 exit(STATE_UNKNOWN); 1243 exit(STATE_UNKNOWN);
1229 } 1244 }
1230 1245
1231 return 0; 1246 return 0;
1232 } 1247}
1233 1248
1234/* open file descriptor and attach */ 1249/* open file descriptor and attach */
1235static int dl_open(const char *dev, int unit, int *fd){ 1250static int dl_open(const char *dev, int unit, int *fd){
@@ -1238,13 +1253,13 @@ static int dl_open(const char *dev, int unit, int *fd){
1238 if((*fd = open(dev, O_RDWR)) == -1){ 1253 if((*fd = open(dev, O_RDWR)) == -1){
1239 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno)); 1254 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno));
1240 exit(STATE_UNKNOWN); 1255 exit(STATE_UNKNOWN);
1241 } 1256 }
1242 attach_req->dl_primitive = DL_ATTACH_REQ; 1257 attach_req->dl_primitive = DL_ATTACH_REQ;
1243 attach_req->dl_ppa = unit; 1258 attach_req->dl_ppa = unit;
1244 put_ctrl(*fd, sizeof(dl_attach_req_t), 0); 1259 put_ctrl(*fd, sizeof(dl_attach_req_t), 0);
1245 get_msg(*fd); 1260 get_msg(*fd);
1246 return check_ctrl(DL_OK_ACK); 1261 return check_ctrl(DL_OK_ACK);
1247 } 1262}
1248 1263
1249/* send DL_BIND_REQ */ 1264/* send DL_BIND_REQ */
1250static int dl_bind(int fd, int sap, u_char *addr){ 1265static int dl_bind(int fd, int sap, u_char *addr){
@@ -1262,12 +1277,12 @@ static int dl_bind(int fd, int sap, u_char *addr){
1262 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){ 1277 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){
1263 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno)); 1278 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno));
1264 exit(STATE_UNKNOWN); 1279 exit(STATE_UNKNOWN);
1265 } 1280 }
1266 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, 1281 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr,
1267 bind_ack->dl_addr_length); 1282 bind_ack->dl_addr_length);
1268 1283
1269 return 0; 1284 return 0;
1270 } 1285}
1271 1286
1272/*********************************************************************** 1287/***********************************************************************
1273 * interface: 1288 * interface:
@@ -1286,15 +1301,15 @@ long mac_addr_dlpi( const char *dev, int unit, u_char *addr){
1286 u_char mac_addr[25]; 1301 u_char mac_addr[25];
1287 1302
1288 if(GOT_ERR != dl_open(dev, unit, &fd)){ 1303 if(GOT_ERR != dl_open(dev, unit, &fd)){
1289 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){ 1304 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){
1290 bcopy( mac_addr, addr, 6); 1305 bcopy( mac_addr, addr, 6);
1291 return 0; 1306 return 0;
1292 }
1293 } 1307 }
1294 close(fd); 1308 }
1309 close(fd);
1295 1310
1296 return -1; 1311 return -1;
1297 } 1312}
1298 1313
1299/* Kompf 2000-2003 */ 1314/* Kompf 2000-2003 */
1300#endif 1315#endif
@@ -1311,7 +1326,7 @@ void resolve_host(const char *in,struct in_addr *out){
1311 1326
1312 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out)); 1327 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out));
1313 freeaddrinfo(ai); 1328 freeaddrinfo(ai);
1314 } 1329}
1315 1330
1316 1331
1317/* parse MAC address string, return 6 bytes (unterminated) or NULL */ 1332/* parse MAC address string, return 6 bytes (unterminated) or NULL */
@@ -1330,10 +1345,10 @@ unsigned char *mac_aton(const char *string){
1330 result[j]=strtol(tmp,(char **)NULL,16); 1345 result[j]=strtol(tmp,(char **)NULL,16);
1331 i++; 1346 i++;
1332 j++; 1347 j++;
1333 } 1348 }
1334 1349
1335 return (j==6) ? result : NULL; 1350 return (j==6) ? result : NULL;
1336 } 1351}
1337 1352
1338 1353
1339void print_hardware_address(const unsigned char *address){ 1354void print_hardware_address(const unsigned char *address){
@@ -1344,7 +1359,7 @@ void print_hardware_address(const unsigned char *address){
1344 printf("%2.2x:", address[i]); 1359 printf("%2.2x:", address[i]);
1345 printf("%2.2x", address[i]); 1360 printf("%2.2x", address[i]);
1346 putchar('\n'); 1361 putchar('\n');
1347 } 1362}
1348 1363
1349 1364
1350/* print usage help */ 1365/* print usage help */
@@ -1357,7 +1372,7 @@ void print_help(void){
1357 1372
1358 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network.")); 1373 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network."));
1359 1374
1360 printf ("\n\n"); 1375 printf ("\n\n");
1361 1376
1362 print_usage(); 1377 print_usage();
1363 1378
@@ -1367,32 +1382,31 @@ void print_help(void){
1367 printf (UT_VERBOSE); 1382 printf (UT_VERBOSE);
1368 1383
1369 printf (" %s\n", "-s, --serverip=IPADDRESS"); 1384 printf (" %s\n", "-s, --serverip=IPADDRESS");
1370 printf (" %s\n", _("IP address of DHCP server that we must hear from")); 1385 printf (" %s\n", _("IP address of DHCP server that we must hear from"));
1371 printf (" %s\n", "-r, --requestedip=IPADDRESS"); 1386 printf (" %s\n", "-r, --requestedip=IPADDRESS");
1372 printf (" %s\n", _("IP address that should be offered by at least one DHCP server")); 1387 printf (" %s\n", _("IP address that should be offered by at least one DHCP server"));
1373 printf (" %s\n", "-t, --timeout=INTEGER"); 1388 printf (" %s\n", "-t, --timeout=INTEGER");
1374 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs")); 1389 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs"));
1375 printf (" %s\n", "-i, --interface=STRING"); 1390 printf (" %s\n", "-i, --interface=STRING");
1376 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)")); 1391 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)"));
1377 printf (" %s\n", "-m, --mac=STRING"); 1392 printf (" %s\n", "-m, --mac=STRING");
1378 printf (" %s\n", _("MAC address to use in the DHCP request")); 1393 printf (" %s\n", _("MAC address to use in the DHCP request"));
1379 printf (" %s\n", "-u, --unicast"); 1394 printf (" %s\n", "-u, --unicast");
1380 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s")); 1395 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
1381 1396 printf (" %s\n", "-x, --exclusive");
1382 printf (UT_SUPPORT); 1397 printf (" %s\n", _("Only requested DHCP server may response (rogue DHCP server detection), requires -s"));
1398
1399 printf (UT_SUPPORT);
1383 return; 1400 return;
1384 } 1401}
1385 1402
1386 1403
1387void 1404void
1388print_usage(void){ 1405print_usage(void){
1389 1406
1390 printf ("%s\n", _("Usage:")); 1407 printf ("%s\n", _("Usage:"));
1391 printf (" %s [-v] [-u] [-s serverip] [-r requestedip] [-t timeout]\n",progname); 1408 printf (" %s [-v] [-u] [-x] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
1392 printf (" [-i interface] [-m mac]\n"); 1409 printf (" [-i interface] [-m mac]\n");
1393 1410
1394 return; 1411 return;
1395 } 1412}
1396
1397
1398
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 1d47e9f..303241d 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -43,7 +43,7 @@ const char *copyright = "2005-2008";
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 */
46#include "common.h" 46#include "../plugins/common.h"
47#include "netutils.h" 47#include "netutils.h"
48#include "utils.h" 48#include "utils.h"
49 49
@@ -109,18 +109,35 @@ typedef struct rta_host {
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 double rtmax; /* max rtt */ 113 double rtmax; /* max rtt */
113 double rtmin; /* min rtt */ 114 double rtmin; /* min rtt */
115 double jitter; /* measured jitter */
116 int jitter_status; // check result for Jitter checks
117 double jitter_max; /* jitter rtt maximum */
118 double jitter_min; /* jitter rtt minimum */
119 double EffectiveLatency;
120 double mos; /* Mean opnion score */
121 int mos_status; // check result for MOS checks
122 double score; /* score */
123 int score_status; // check result for score checks
124 u_int last_tdiff;
125 u_int last_icmp_seq; /* Last ICMP_SEQ to check out of order pkts */
114 unsigned char pl; /* measured packet loss */ 126 unsigned char pl; /* measured packet loss */
127 int pl_status; // check result for packet loss checks
115 struct rta_host *next; /* linked list */ 128 struct rta_host *next; /* linked list */
129 int order_status; // check result for packet order checks
116} rta_host; 130} rta_host;
117 131
118#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */ 132#define FLAG_LOST_CAUSE 0x01 /* decidedly dead target. */
119 133
120/* threshold structure. all values are maximum allowed, exclusive */ 134/* threshold structure. all values are maximum allowed, exclusive */
121typedef struct threshold { 135typedef struct threshold {
122 unsigned char pl; /* max allowed packet loss in percent */ 136 unsigned char pl; /* max allowed packet loss in percent */
123 unsigned int rta; /* roundtrip time average, microseconds */ 137 unsigned int rta; /* roundtrip time average, microseconds */
138 double jitter; /* jitter time average, microseconds */
139 double mos; /* MOS */
140 double score; /* Score */
124} threshold; 141} threshold;
125 142
126/* the data structure */ 143/* the data structure */
@@ -159,6 +176,16 @@ typedef union icmp_packet {
159#define MODE_ALL 2 176#define MODE_ALL 2
160#define MODE_ICMP 3 177#define MODE_ICMP 3
161 178
179enum enum_threshold_mode {
180 const_rta_mode,
181 const_packet_loss_mode,
182 const_jitter_mode,
183 const_mos_mode,
184 const_score_mode
185};
186
187typedef enum enum_threshold_mode threshold_mode;
188
162/* the different ping types we can do 189/* the different ping types we can do
163 * TODO: investigate ARP ping as well */ 190 * TODO: investigate ARP ping as well */
164#define HAVE_ICMP 1 191#define HAVE_ICMP 1
@@ -188,6 +215,8 @@ static int wait_for_reply(int, u_int);
188static 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*);
189static int send_icmp_ping(int, struct rta_host *); 216static int send_icmp_ping(int, struct rta_host *);
190static 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);
219static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode);
191static void run_checks(void); 220static void run_checks(void);
192static void set_source_ip(char *); 221static void set_source_ip(char *);
193static int add_target(char *); 222static int add_target(char *);
@@ -199,13 +228,28 @@ static void finish(int);
199static void crash(const char *, ...); 228static void crash(const char *, ...);
200 229
201/** external **/ 230/** external **/
202extern int optind, opterr, optopt; 231extern int optind;
203extern char *optarg; 232extern char *optarg;
204extern char **environ; 233extern char **environ;
205 234
206/** global variables **/ 235/** global variables **/
207static struct rta_host **table, *cursor, *list; 236static struct rta_host **table, *cursor, *list;
208static threshold crit = {80, 500000}, warn = {40, 200000}; 237
238static threshold crit = {
239 .pl = 80,
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
209static int mode, protocols, sockets, debug = 0, timeout = 10; 253static int mode, protocols, sockets, debug = 0, timeout = 10;
210static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; 254static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE;
211static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN; 255static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN;
@@ -224,6 +268,12 @@ static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values
224static int min_hosts_alive = -1; 268static int min_hosts_alive = -1;
225float pkt_backoff_factor = 1.5; 269float pkt_backoff_factor = 1.5;
226float target_backoff_factor = 1.5; 270float target_backoff_factor = 1.5;
271bool rta_mode=false;
272bool pl_mode=false;
273bool jitter_mode=false;
274bool score_mode=false;
275bool mos_mode=false;
276bool order_mode=false;
227 277
228/** code start **/ 278/** code start **/
229static void 279static void
@@ -393,12 +443,14 @@ main(int argc, char **argv)
393 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno; 443 int icmp_sockerrno, udp_sockerrno, tcp_sockerrno;
394 int result; 444 int result;
395 struct rta_host *host; 445 struct rta_host *host;
446#ifdef HAVE_SIGACTION
447 struct sigaction sig_action;
448#endif
396#ifdef SO_TIMESTAMP 449#ifdef SO_TIMESTAMP
397 int on = 1; 450 int on = 1;
398#endif 451#endif
399 char *source_ip = NULL; 452 char *source_ip = NULL;
400 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64"; 453 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:P:R:J:S:M:O64";
401
402 setlocale (LC_ALL, ""); 454 setlocale (LC_ALL, "");
403 bindtextdomain (PACKAGE, LOCALEDIR); 455 bindtextdomain (PACKAGE, LOCALEDIR);
404 textdomain (PACKAGE); 456 textdomain (PACKAGE);
@@ -407,7 +459,7 @@ main(int argc, char **argv)
407 * that before pointer magic (esp. on network data) */ 459 * that before pointer magic (esp. on network data) */
408 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; 460 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0;
409 461
410 address_family = -1; 462 address_family = -1;
411 int icmp_proto = IPPROTO_ICMP; 463 int icmp_proto = IPPROTO_ICMP;
412 464
413 /* get calling name the old-fashioned way for portability instead 465 /* get calling name the old-fashioned way for portability instead
@@ -422,10 +474,19 @@ main(int argc, char **argv)
422 table = NULL; 474 table = NULL;
423 475
424 mode = MODE_RTA; 476 mode = MODE_RTA;
477 /* Default critical thresholds */
425 crit.rta = 500000; 478 crit.rta = 500000;
426 crit.pl = 80; 479 crit.pl = 80;
480 crit.jitter = 50;
481 crit.mos= 3;
482 crit.score=70;
483 /* Default warning thresholds */
427 warn.rta = 200000; 484 warn.rta = 200000;
428 warn.pl = 40; 485 warn.pl = 40;
486 warn.jitter = 40;
487 warn.mos= 3.5;
488 warn.score=80;
489
429 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP; 490 protocols = HAVE_ICMP | HAVE_UDP | HAVE_TCP;
430 pkt_interval = 80000; /* 80 msec packet interval by default */ 491 pkt_interval = 80000; /* 80 msec packet interval by default */
431 packets = 5; 492 packets = 5;
@@ -481,7 +542,8 @@ main(int argc, char **argv)
481 /* Reset argument scanning */ 542 /* Reset argument scanning */
482 optind = 1; 543 optind = 1;
483 544
484 unsigned short size; 545 unsigned long size;
546 bool err;
485 /* parse the arguments */ 547 /* parse the arguments */
486 for(i = 1; i < argc; i++) { 548 for(i = 1; i < argc; i++) {
487 while((arg = getopt(argc, argv, opts_str)) != EOF) { 549 while((arg = getopt(argc, argv, opts_str)) != EOF) {
@@ -490,7 +552,7 @@ main(int argc, char **argv)
490 debug++; 552 debug++;
491 break; 553 break;
492 case 'b': 554 case 'b':
493 size = (unsigned short)strtol(optarg,NULL,0); 555 size = strtol(optarg,NULL,0);
494 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) && 556 if (size >= (sizeof(struct icmp) + sizeof(struct icmp_ping_data)) &&
495 size < MAX_PING_DATA) { 557 size < MAX_PING_DATA) {
496 icmp_data_size = size; 558 icmp_data_size = size;
@@ -545,6 +607,49 @@ main(int argc, char **argv)
545 print_help (); 607 print_help ();
546 exit (STATE_UNKNOWN); 608 exit (STATE_UNKNOWN);
547 break; 609 break;
610 case 'R': /* RTA mode */
611 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_rta_mode);
612 if (!err) {
613 crash("Failed to parse RTA threshold");
614 }
615
616 rta_mode=true;
617 break;
618 case 'P': /* packet loss mode */
619 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_packet_loss_mode);
620 if (!err) {
621 crash("Failed to parse packet loss threshold");
622 }
623
624 pl_mode=true;
625 break;
626 case 'J': /* jitter mode */
627 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_jitter_mode);
628 if (!err) {
629 crash("Failed to parse jitter threshold");
630 }
631
632 jitter_mode=true;
633 break;
634 case 'M': /* MOS mode */
635 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_mos_mode);
636 if (!err) {
637 crash("Failed to parse MOS threshold");
638 }
639
640 mos_mode=true;
641 break;
642 case 'S': /* score mode */
643 err = get_threshold2(optarg, strlen(optarg), &warn, &crit, const_score_mode);
644 if (!err) {
645 crash("Failed to parse score threshold");
646 }
647
648 score_mode=true;
649 break;
650 case 'O': /* out of order mode */
651 order_mode=true;
652 break;
548 } 653 }
549 } 654 }
550 } 655 }
@@ -565,10 +670,10 @@ main(int argc, char **argv)
565 add_target(*argv); 670 add_target(*argv);
566 argv++; 671 argv++;
567 } 672 }
673
568 if(!targets) { 674 if(!targets) {
569 errno = 0; 675 errno = 0;
570 crash("No hosts to check"); 676 crash("No hosts to check");
571 exit(3);
572 } 677 }
573 678
574 // add_target might change address_family 679 // add_target might change address_family
@@ -631,11 +736,25 @@ main(int argc, char **argv)
631 if(warn.pl > crit.pl) warn.pl = crit.pl; 736 if(warn.pl > crit.pl) warn.pl = crit.pl;
632 if(warn.rta > crit.rta) warn.rta = crit.rta; 737 if(warn.rta > crit.rta) warn.rta = crit.rta;
633 if(warn_down > crit_down) crit_down = warn_down; 738 if(warn_down > crit_down) crit_down = warn_down;
634 739 if(warn.jitter > crit.jitter) crit.jitter = warn.jitter;
740 if(warn.mos < crit.mos) warn.mos = crit.mos;
741 if(warn.score < crit.score) warn.score = crit.score;
742
743#ifdef HAVE_SIGACTION
744 sig_action.sa_sigaction = NULL;
745 sig_action.sa_handler = finish;
746 sigfillset(&sig_action.sa_mask);
747 sig_action.sa_flags = SA_NODEFER|SA_RESTART;
748 sigaction(SIGINT, &sig_action, NULL);
749 sigaction(SIGHUP, &sig_action, NULL);
750 sigaction(SIGTERM, &sig_action, NULL);
751 sigaction(SIGALRM, &sig_action, NULL);
752#else /* HAVE_SIGACTION */
635 signal(SIGINT, finish); 753 signal(SIGINT, finish);
636 signal(SIGHUP, finish); 754 signal(SIGHUP, finish);
637 signal(SIGTERM, finish); 755 signal(SIGTERM, finish);
638 signal(SIGALRM, finish); 756 signal(SIGALRM, finish);
757#endif /* HAVE_SIGACTION */
639 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout); 758 if(debug) printf("Setting alarm timeout to %u seconds\n", timeout);
640 alarm(timeout); 759 alarm(timeout);
641 760
@@ -685,7 +804,11 @@ main(int argc, char **argv)
685 } 804 }
686 805
687 host = list; 806 host = list;
688 table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets); 807 table = malloc(sizeof(struct rta_host *) * targets);
808 if(!table) {
809 crash("main(): malloc failed for host table");
810 }
811
689 i = 0; 812 i = 0;
690 while(host) { 813 while(host) {
691 host->id = i*packets; 814 host->id = i*packets;
@@ -772,6 +895,7 @@ wait_for_reply(int sock, u_int t)
772 struct icmp_ping_data data; 895 struct icmp_ping_data data;
773 struct timeval wait_start, now; 896 struct timeval wait_start, now;
774 u_int tdiff, i, per_pkt_wait; 897 u_int tdiff, i, per_pkt_wait;
898 double jitter_tmp;
775 899
776 if (!(packet.buf = malloc(icmp_pkt_size))) { 900 if (!(packet.buf = malloc(icmp_pkt_size))) {
777 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 901 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
@@ -890,12 +1014,44 @@ wait_for_reply(int sock, u_int t)
890 1014
891 tdiff = get_timevaldiff(&data.stime, &now); 1015 tdiff = get_timevaldiff(&data.stime, &now);
892 1016
1017 if (host->last_tdiff>0) {
1018 /* Calculate jitter */
1019 if (host->last_tdiff > tdiff) {
1020 jitter_tmp = host->last_tdiff - tdiff;
1021 } else {
1022 jitter_tmp = tdiff - host->last_tdiff;
1023 }
1024
1025 if (host->jitter==0) {
1026 host->jitter=jitter_tmp;
1027 host->jitter_max=jitter_tmp;
1028 host->jitter_min=jitter_tmp;
1029 } else {
1030 host->jitter+=jitter_tmp;
1031
1032 if (jitter_tmp < host->jitter_min) {
1033 host->jitter_min=jitter_tmp;
1034 }
1035
1036 if (jitter_tmp > host->jitter_max) {
1037 host->jitter_max=jitter_tmp;
1038 }
1039 }
1040
1041 /* Check if packets in order */
1042 if (host->last_icmp_seq >= packet.icp->icmp_seq)
1043 host->order_status=STATE_CRITICAL;
1044 }
1045 host->last_tdiff=tdiff;
1046
1047 host->last_icmp_seq=packet.icp->icmp_seq;
1048
893 host->time_waited += tdiff; 1049 host->time_waited += tdiff;
894 host->icmp_recv++; 1050 host->icmp_recv++;
895 icmp_recv++; 1051 icmp_recv++;
896 if (tdiff > host->rtmax) 1052 if (tdiff > (unsigned int)host->rtmax)
897 host->rtmax = tdiff; 1053 host->rtmax = tdiff;
898 if (tdiff < host->rtmin) 1054 if (tdiff < (unsigned int)host->rtmin)
899 host->rtmin = tdiff; 1055 host->rtmin = tdiff;
900 1056
901 if(debug) { 1057 if(debug) {
@@ -1056,7 +1212,9 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1056 int n, ret; 1212 int n, ret;
1057 struct timeval to, then, now; 1213 struct timeval to, then, now;
1058 fd_set rd, wr; 1214 fd_set rd, wr;
1215#ifdef HAVE_MSGHDR_MSG_CONTROL
1059 char ans_data[4096]; 1216 char ans_data[4096];
1217#endif // HAVE_MSGHDR_MSG_CONTROL
1060 struct msghdr hdr; 1218 struct msghdr hdr;
1061 struct iovec iov; 1219 struct iovec iov;
1062#ifdef SO_TIMESTAMP 1220#ifdef SO_TIMESTAMP
@@ -1094,8 +1252,10 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
1094 hdr.msg_namelen = slen; 1252 hdr.msg_namelen = slen;
1095 hdr.msg_iov = &iov; 1253 hdr.msg_iov = &iov;
1096 hdr.msg_iovlen = 1; 1254 hdr.msg_iovlen = 1;
1255#ifdef HAVE_MSGHDR_MSG_CONTROL
1097 hdr.msg_control = ans_data; 1256 hdr.msg_control = ans_data;
1098 hdr.msg_controllen = sizeof(ans_data); 1257 hdr.msg_controllen = sizeof(ans_data);
1258#endif
1099 1259
1100 ret = recvmsg(sock, &hdr, 0); 1260 ret = recvmsg(sock, &hdr, 0);
1101#ifdef SO_TIMESTAMP 1261#ifdef SO_TIMESTAMP
@@ -1125,6 +1285,8 @@ finish(int sig)
1125 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"}; 1285 {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
1126 int hosts_ok = 0; 1286 int hosts_ok = 0;
1127 int hosts_warn = 0; 1287 int hosts_warn = 0;
1288 int this_status;
1289 double R;
1128 1290
1129 alarm(0); 1291 alarm(0);
1130 if(debug > 1) printf("finish(%d) called\n", sig); 1292 if(debug > 1) printf("finish(%d) called\n", sig);
@@ -1140,9 +1302,12 @@ finish(int sig)
1140 } 1302 }
1141 1303
1142 /* iterate thrice to calculate values, give output, and print perfparse */ 1304 /* iterate thrice to calculate values, give output, and print perfparse */
1305 status=STATE_OK;
1143 host = list; 1306 host = list;
1144 1307
1145 while(host) { 1308 while(host) {
1309 this_status = STATE_OK;
1310
1146 if(!host->icmp_recv) { 1311 if(!host->icmp_recv) {
1147 /* rta 0 is ofcourse not entirely correct, but will still show up 1312 /* rta 0 is ofcourse not entirely correct, but will still show up
1148 * conspicuously as missing entries in perfparse and cacti */ 1313 * conspicuously as missing entries in perfparse and cacti */
@@ -1151,26 +1316,138 @@ finish(int sig)
1151 status = STATE_CRITICAL; 1316 status = STATE_CRITICAL;
1152 /* up the down counter if not already counted */ 1317 /* up the down counter if not already counted */
1153 if(!(host->flags & FLAG_LOST_CAUSE) && targets_alive) targets_down++; 1318 if(!(host->flags & FLAG_LOST_CAUSE) && targets_alive) targets_down++;
1154 } 1319 } else {
1155 else {
1156 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent; 1320 pl = ((host->icmp_sent - host->icmp_recv) * 100) / host->icmp_sent;
1157 rta = (double)host->time_waited / host->icmp_recv; 1321 rta = (double)host->time_waited / host->icmp_recv;
1158 } 1322 }
1323
1324 if (host->icmp_recv>1) {
1325 /*
1326 * 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
1328 * It calculates a MOS value (range of 1 to 5, where 1 is bad and 5 really good).
1329 * According to some quick research MOS originates from the Audio/Video transport network area.
1330 * Whether it can and should be computed from ICMP data, I can not say.
1331 *
1332 * Anyway the basic idea is to map a value "R" with a range of 0-100 to the MOS value
1333 *
1334 * MOS stands likely for Mean Opinion Score ( https://en.wikipedia.org/wiki/Mean_Opinion_Score )
1335 *
1336 * More links:
1337 * - https://confluence.slac.stanford.edu/display/IEPM/MOS
1338 */
1339 host->jitter=(host->jitter / (host->icmp_recv - 1)/1000);
1340
1341 /*
1342 * Take the average round trip latency (in milliseconds), add
1343 * round trip jitter, but double the impact to latency
1344 * then add 10 for protocol latencies (in milliseconds).
1345 */
1346 host->EffectiveLatency = (rta/1000) + host->jitter * 2 + 10;
1347
1348 if (host->EffectiveLatency < 160) {
1349 R = 93.2 - (host->EffectiveLatency / 40);
1350 } else {
1351 R = 93.2 - ((host->EffectiveLatency - 120) / 10);
1352 }
1353
1354 // Now, let us deduct 2.5 R values per percentage of packet loss (i.e. a
1355 // loss of 5% will be entered as 5).
1356 R = R - (pl * 2.5);
1357
1358 if (R < 0) {
1359 R = 0;
1360 }
1361
1362 host->score = R;
1363 host->mos= 1 + ((0.035) * R) + ((.000007) * R * (R-60) * (100-R));
1364 } else {
1365 host->jitter=0;
1366 host->jitter_min=0;
1367 host->jitter_max=0;
1368 host->mos=0;
1369 }
1370
1159 host->pl = pl; 1371 host->pl = pl;
1160 host->rta = rta; 1372 host->rta = rta;
1161 if(pl >= crit.pl || rta >= crit.rta) { 1373
1162 status = STATE_CRITICAL; 1374 /* if no new mode selected, use old schema */
1375 if (!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && !order_mode) {
1376 rta_mode = true;
1377 pl_mode = true;
1163 } 1378 }
1164 else if(!status && (pl >= warn.pl || rta >= warn.rta)) { 1379
1165 status = STATE_WARNING; 1380 /* Check which mode is on and do the warn / Crit stuff */
1166 hosts_warn++; 1381 if (rta_mode) {
1382 if(rta >= crit.rta) {
1383 this_status = STATE_CRITICAL;
1384 status = STATE_CRITICAL;
1385 host->rta_status=STATE_CRITICAL;
1386 } else if(status!=STATE_CRITICAL && (rta >= warn.rta)) {
1387 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1388 status = STATE_WARNING;
1389 host->rta_status=STATE_WARNING;
1390 }
1391 }
1392
1393 if (pl_mode) {
1394 if(pl >= crit.pl) {
1395 this_status = STATE_CRITICAL;
1396 status = STATE_CRITICAL;
1397 host->pl_status=STATE_CRITICAL;
1398 } else if(status!=STATE_CRITICAL && (pl >= warn.pl)) {
1399 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1400 status = STATE_WARNING;
1401 host->pl_status=STATE_WARNING;
1402 }
1403 }
1404
1405 if (jitter_mode) {
1406 if(host->jitter >= crit.jitter) {
1407 this_status = STATE_CRITICAL;
1408 status = STATE_CRITICAL;
1409 host->jitter_status=STATE_CRITICAL;
1410 } else if(status!=STATE_CRITICAL && (host->jitter >= warn.jitter)) {
1411 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1412 status = STATE_WARNING;
1413 host->jitter_status=STATE_WARNING;
1414 }
1415 }
1416
1417 if (mos_mode) {
1418 if(host->mos <= crit.mos) {
1419 this_status = STATE_CRITICAL;
1420 status = STATE_CRITICAL;
1421 host->mos_status=STATE_CRITICAL;
1422 } else if(status!=STATE_CRITICAL && (host->mos <= warn.mos)) {
1423 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1424 status = STATE_WARNING;
1425 host->mos_status=STATE_WARNING;
1426 }
1427 }
1428
1429 if (score_mode) {
1430 if(host->score <= crit.score) {
1431 this_status = STATE_CRITICAL;
1432 status = STATE_CRITICAL;
1433 host->score_status=STATE_CRITICAL;
1434 } else if(status!=STATE_CRITICAL && (host->score <= warn.score)) {
1435 this_status = (this_status <= STATE_WARNING ? STATE_WARNING : this_status);
1436 status = STATE_WARNING;
1437 host->score_status=STATE_WARNING;
1438 }
1167 } 1439 }
1168 else { 1440
1441 if (this_status == STATE_WARNING) {
1442 hosts_warn++;
1443 } else if (this_status == STATE_OK) {
1169 hosts_ok++; 1444 hosts_ok++;
1170 } 1445 }
1171 1446
1172 host = host->next; 1447 host = host->next;
1173 } 1448 }
1449
1450
1174 /* this is inevitable */ 1451 /* this is inevitable */
1175 if(!targets_alive) status = STATE_CRITICAL; 1452 if(!targets_alive) status = STATE_CRITICAL;
1176 if(min_hosts_alive > -1) { 1453 if(min_hosts_alive > -1) {
@@ -1181,6 +1458,7 @@ finish(int sig)
1181 1458
1182 host = list; 1459 host = list;
1183 while(host) { 1460 while(host) {
1461
1184 if(debug) puts(""); 1462 if(debug) puts("");
1185 if(i) { 1463 if(i) {
1186 if(i < targets) printf(" :: "); 1464 if(i < targets) printf(" :: ");
@@ -1189,6 +1467,8 @@ finish(int sig)
1189 i++; 1467 i++;
1190 if(!host->icmp_recv) { 1468 if(!host->icmp_recv) {
1191 status = STATE_CRITICAL; 1469 status = STATE_CRITICAL;
1470 host->rtmin=0;
1471 host->jitter_min=0;
1192 if(host->flags & FLAG_LOST_CAUSE) { 1472 if(host->flags & FLAG_LOST_CAUSE) {
1193 char address[INET6_ADDRSTRLEN]; 1473 char address[INET6_ADDRSTRLEN];
1194 parse_address(&host->error_addr, address, sizeof(address)); 1474 parse_address(&host->error_addr, address, sizeof(address));
@@ -1197,31 +1477,117 @@ finish(int sig)
1197 get_icmp_error_msg(host->icmp_type, host->icmp_code), 1477 get_icmp_error_msg(host->icmp_type, host->icmp_code),
1198 address, 1478 address,
1199 100); 1479 100);
1200 } 1480 } else { /* not marked as lost cause, so we have no flags for it */
1201 else { /* not marked as lost cause, so we have no flags for it */
1202 printf("%s: rta nan, lost 100%%", host->name); 1481 printf("%s: rta nan, lost 100%%", host->name);
1203 } 1482 }
1483 } else { /* !icmp_recv */
1484 printf("%s", host->name);
1485 /* rta text output */
1486 if (rta_mode) {
1487 if (status == STATE_OK)
1488 printf(" rta %0.3fms", host->rta / 1000);
1489 else if (status==STATE_WARNING && host->rta_status==status)
1490 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)warn.rta/1000);
1491 else if (status==STATE_CRITICAL && host->rta_status==status)
1492 printf(" rta %0.3fms > %0.3fms", (float)host->rta / 1000, (float)crit.rta/1000);
1493 }
1494 /* pl text output */
1495 if (pl_mode) {
1496 if (status == STATE_OK)
1497 printf(" lost %u%%", host->pl);
1498 else if (status==STATE_WARNING && host->pl_status==status)
1499 printf(" lost %u%% > %u%%", host->pl, warn.pl);
1500 else if (status==STATE_CRITICAL && host->pl_status==status)
1501 printf(" lost %u%% > %u%%", host->pl, crit.pl);
1502 }
1503 /* jitter text output */
1504 if (jitter_mode) {
1505 if (status == STATE_OK)
1506 printf(" jitter %0.3fms", (float)host->jitter);
1507 else if (status==STATE_WARNING && host->jitter_status==status)
1508 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, warn.jitter);
1509 else if (status==STATE_CRITICAL && host->jitter_status==status)
1510 printf(" jitter %0.3fms > %0.3fms", (float)host->jitter, crit.jitter);
1511 }
1512 /* mos text output */
1513 if (mos_mode) {
1514 if (status == STATE_OK)
1515 printf(" MOS %0.1f", (float)host->mos);
1516 else if (status==STATE_WARNING && host->mos_status==status)
1517 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)warn.mos);
1518 else if (status==STATE_CRITICAL && host->mos_status==status)
1519 printf(" MOS %0.1f < %0.1f", (float)host->mos, (float)crit.mos);
1520 }
1521 /* score text output */
1522 if (score_mode) {
1523 if (status == STATE_OK)
1524 printf(" Score %u", (int)host->score);
1525 else if (status==STATE_WARNING && host->score_status==status )
1526 printf(" Score %u < %u", (int)host->score, (int)warn.score);
1527 else if (status==STATE_CRITICAL && host->score_status==status )
1528 printf(" Score %u < %u", (int)host->score, (int)crit.score);
1529 }
1530 /* order statis text output */
1531 if (order_mode) {
1532 if (status == STATE_OK)
1533 printf(" Packets in order");
1534 else if (status==STATE_CRITICAL && host->order_status==status)
1535 printf(" Packets out of order");
1536 }
1204 } 1537 }
1205 else { /* !icmp_recv */
1206 printf("%s: rta %0.3fms, lost %u%%",
1207 host->name, host->rta / 1000, host->pl);
1208 }
1209
1210 host = host->next; 1538 host = host->next;
1211 } 1539 }
1212 1540
1213 /* iterate once more for pretty perfparse output */ 1541 /* iterate once more for pretty perfparse output */
1214 printf("|"); 1542 if (!(!rta_mode && !pl_mode && !jitter_mode && !score_mode && !mos_mode && order_mode)) {
1543 printf("|");
1544 }
1215 i = 0; 1545 i = 0;
1216 host = list; 1546 host = list;
1217 while(host) { 1547 while(host) {
1218 if(debug) puts(""); 1548 if(debug) puts("");
1219 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %spl=%u%%;%u;%u;; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ", 1549
1550 if (rta_mode && host->pl<100) {
1551 printf("%srta=%0.3fms;%0.3f;%0.3f;0; %srtmax=%0.3fms;;;; %srtmin=%0.3fms;;;; ",
1220 (targets > 1) ? host->name : "", 1552 (targets > 1) ? host->name : "",
1221 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1553 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000,
1222 (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl,
1223 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1554 (targets > 1) ? host->name : "", (float)host->rtmax / 1000,
1224 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0); 1555 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1556 }
1557
1558 if (pl_mode) {
1559 printf("%spl=%u%%;%u;%u;0;100 ", (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl);
1560 }
1561
1562 if (jitter_mode && host->pl<100) {
1563 printf("%sjitter_avg=%0.3fms;%0.3f;%0.3f;0; %sjitter_max=%0.3fms;;;; %sjitter_min=%0.3fms;;;; ",
1564 (targets > 1) ? host->name : "",
1565 (float)host->jitter,
1566 (float)warn.jitter,
1567 (float)crit.jitter,
1568 (targets > 1) ? host->name : "",
1569 (float)host->jitter_max / 1000, (targets > 1) ? host->name : "",
1570 (float)host->jitter_min / 1000
1571 );
1572 }
1573
1574 if (mos_mode && host->pl<100) {
1575 printf("%smos=%0.1f;%0.1f;%0.1f;0;5 ",
1576 (targets > 1) ? host->name : "",
1577 (float)host->mos,
1578 (float)warn.mos,
1579 (float)crit.mos
1580 );
1581 }
1582
1583 if (score_mode && host->pl<100) {
1584 printf("%sscore=%u;%u;%u;0;100 ",
1585 (targets > 1) ? host->name : "",
1586 (int)host->score,
1587 (int)warn.score,
1588 (int)crit.score
1589 );
1590 }
1225 1591
1226 host = host->next; 1592 host = host->next;
1227 } 1593 }
@@ -1312,6 +1678,7 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1312 /* set the values. use calling name for output */ 1678 /* set the values. use calling name for output */
1313 host->name = strdup(arg); 1679 host->name = strdup(arg);
1314 1680
1681
1315 /* fill out the sockaddr_storage struct */ 1682 /* fill out the sockaddr_storage struct */
1316 if(address_family == AF_INET) { 1683 if(address_family == AF_INET) {
1317 host_sin = (struct sockaddr_in *)&host->saddr_in; 1684 host_sin = (struct sockaddr_in *)&host->saddr_in;
@@ -1324,7 +1691,22 @@ add_target_ip(char *arg, struct sockaddr_storage *in)
1324 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr); 1691 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
1325 } 1692 }
1326 1693
1694 /* fill out the sockaddr_in struct */
1327 host->rtmin = INFINITY; 1695 host->rtmin = INFINITY;
1696 host->rtmax = 0;
1697 host->jitter=0;
1698 host->jitter_max=0;
1699 host->jitter_min=INFINITY;
1700 host->last_tdiff=0;
1701 host->order_status=STATE_OK;
1702 host->last_icmp_seq=0;
1703 host->rta_status=0;
1704 host->pl_status=0;
1705 host->jitter_status=0;
1706 host->mos_status=0;
1707 host->score_status=0;
1708 host->pl_status=0;
1709
1328 1710
1329 if(!list) list = cursor = host; 1711 if(!list) list = cursor = host;
1330 else cursor->next = host; 1712 else cursor->next = host;
@@ -1408,7 +1790,7 @@ add_target(char *arg)
1408 } 1790 }
1409 break; 1791 break;
1410 } 1792 }
1411 freeaddrinfo(res); 1793 freeaddrinfo(res);
1412 1794
1413 return 0; 1795 return 0;
1414} 1796}
@@ -1472,7 +1854,7 @@ get_timevar(const char *str)
1472 1854
1473 /* unit might be given as ms|m (millisec), 1855 /* unit might be given as ms|m (millisec),
1474 * us|u (microsec) or just plain s, for seconds */ 1856 * us|u (microsec) or just plain s, for seconds */
1475 u = p = '\0'; 1857 p = '\0';
1476 u = str[len - 1]; 1858 u = str[len - 1];
1477 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2]; 1859 if(len >= 2 && !isdigit((int)str[len - 2])) p = str[len - 2];
1478 if(p && u == 's') u = p; 1860 if(p && u == 's') u = p;
@@ -1530,6 +1912,81 @@ get_threshold(char *str, threshold *th)
1530 return 0; 1912 return 0;
1531} 1913}
1532 1914
1915/*
1916 * This functions receives a pointer to a string which should contain a threshold for the
1917 * rta, packet_loss, jitter, mos or score mode in the form number,number[m|%]* assigns the
1918 * parsed number to the corresponding threshold variable.
1919 * @param[in,out] str String containing the given threshold values
1920 * @param[in] length strlen(str)
1921 * @param[out] warn Pointer to the warn threshold struct to which the values should be assigned
1922 * @param[out] crit Pointer to the crit threshold struct to which the values should be assigned
1923 * @param[in] mode Determines whether this a threshold for rta, packet_loss, jitter, mos or score (exclusively)
1924 */
1925static bool get_threshold2(char *str, size_t length, threshold *warn, threshold *crit, threshold_mode mode) {
1926 if (!str || !length || !warn || !crit) return false;
1927
1928
1929 // p points to the last char in str
1930 char *p = &str[length - 1];
1931
1932 // first_iteration is bof-stop on stupid libc's
1933 bool first_iteration = true;
1934
1935 while(p != &str[0]) {
1936 if( (*p == 'm') || (*p == '%') ) {
1937 *p = '\0';
1938 } else if(*p == ',' && !first_iteration) {
1939 *p = '\0'; /* reset it so get_timevar(str) works nicely later */
1940
1941 char *start_of_value = p + 1;
1942
1943 if (!parse_threshold2_helper(start_of_value, strlen(start_of_value), crit, mode)){
1944 return false;
1945 }
1946
1947 }
1948 first_iteration = false;
1949 p--;
1950 }
1951
1952 return parse_threshold2_helper(p, strlen(p), warn, mode);
1953}
1954
1955static bool parse_threshold2_helper(char *s, size_t length, threshold *thr, threshold_mode mode) {
1956 char *resultChecker = {0};
1957
1958 switch (mode) {
1959 case const_rta_mode:
1960 thr->rta = strtod(s, &resultChecker) * 1000;
1961 break;
1962 case const_packet_loss_mode:
1963 thr->pl = (unsigned char)strtoul(s, &resultChecker, 0);
1964 break;
1965 case const_jitter_mode:
1966 thr->jitter = strtod(s, &resultChecker);
1967
1968 break;
1969 case const_mos_mode:
1970 thr->mos = strtod(s, &resultChecker);
1971 break;
1972 case const_score_mode:
1973 thr->score = strtod(s, &resultChecker);
1974 break;
1975 }
1976
1977 if (resultChecker == s) {
1978 // Failed to parse
1979 return false;
1980 }
1981
1982 if (resultChecker != (s + length)) {
1983 // Trailing symbols
1984 return false;
1985 }
1986
1987 return true;
1988}
1989
1533unsigned short 1990unsigned short
1534icmp_checksum(uint16_t *p, size_t n) 1991icmp_checksum(uint16_t *p, size_t n)
1535{ 1992{
@@ -1555,74 +2012,91 @@ icmp_checksum(uint16_t *p, size_t n)
1555void 2012void
1556print_help(void) 2013print_help(void)
1557{ 2014{
1558 2015 /*print_revision (progname);*/ /* FIXME: Why? */
1559 /*print_revision (progname);*/ /* FIXME: Why? */ 2016 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
1560 2017
1561 printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n"); 2018 printf (COPYRIGHT, copyright, email);
1562 printf (COPYRIGHT, copyright, email); 2019
1563 2020 printf ("\n\n");
1564 printf ("\n\n"); 2021
1565 2022 print_usage ();
1566 print_usage (); 2023
1567 2024 printf (UT_HELP_VRSN);
1568 printf (UT_HELP_VRSN); 2025 printf (UT_EXTRA_OPTS);
1569 printf (UT_EXTRA_OPTS); 2026
1570 2027 printf (" %s\n", "-H");
1571 printf (" %s\n", "-H"); 2028 printf (" %s\n", _("specify a target"));
1572 printf (" %s\n", _("specify a target")); 2029 printf (" %s\n", "[-4|-6]");
1573 printf (" %s\n", "[-4|-6]"); 2030 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets"));
1574 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets")); 2031 printf (" %s\n", "-w");
1575 printf (" %s\n", "-w"); 2032 printf (" %s", _("warning threshold (currently "));
1576 printf (" %s", _("warning threshold (currently ")); 2033 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
1577 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); 2034 printf (" %s\n", "-c");
1578 printf (" %s\n", "-c"); 2035 printf (" %s", _("critical threshold (currently "));
1579 printf (" %s", _("critical threshold (currently ")); 2036 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl);
1580 printf ("%0.3fms,%u%%)\n", (float)crit.rta / 1000, crit.pl); 2037
1581 printf (" %s\n", "-s"); 2038 printf (" %s\n", "-R");
1582 printf (" %s\n", _("specify a source IP address or device name")); 2039 printf (" %s\n", _("RTA, round trip average, mode warning,critical, ex. 100ms,200ms unit in ms"));
1583 printf (" %s\n", "-n"); 2040 printf (" %s\n", "-P");
1584 printf (" %s", _("number of packets to send (currently ")); 2041 printf (" %s\n", _("packet loss mode, ex. 40%,50% , unit in %"));
1585 printf ("%u)\n",packets); 2042 printf (" %s\n", "-J");
1586 printf (" %s\n", "-i"); 2043 printf (" %s\n", _("jitter mode warning,critical, ex. 40.000ms,50.000ms , unit in ms "));
1587 printf (" %s", _("max packet interval (currently ")); 2044 printf (" %s\n", "-M");
1588 printf ("%0.3fms)\n",(float)pkt_interval / 1000); 2045 printf (" %s\n", _("MOS mode, between 0 and 4.4 warning,critical, ex. 3.5,3.0"));
1589 printf (" %s\n", "-I"); 2046 printf (" %s\n", "-S");
1590 printf (" %s", _("max target interval (currently ")); 2047 printf (" %s\n", _("score mode, max value 100 warning,critical, ex. 80,70 "));
1591 printf ("%0.3fms)\n", (float)target_interval / 1000); 2048 printf (" %s\n", "-O");
1592 printf (" %s\n", "-m"); 2049 printf (" %s\n", _("detect out of order ICMP packts "));
1593 printf (" %s",_("number of alive hosts required for success")); 2050 printf (" %s\n", "-H");
1594 printf ("\n"); 2051 printf (" %s\n", _("specify a target"));
1595 printf (" %s\n", "-l"); 2052 printf (" %s\n", "-s");
1596 printf (" %s", _("TTL on outgoing packets (currently ")); 2053 printf (" %s\n", _("specify a source IP address or device name"));
1597 printf ("%u)\n", ttl); 2054 printf (" %s\n", "-n");
1598 printf (" %s\n", "-t"); 2055 printf (" %s", _("number of packets to send (currently "));
1599 printf (" %s",_("timeout value (seconds, currently ")); 2056 printf ("%u)\n",packets);
1600 printf ("%u)\n", timeout); 2057 printf (" %s\n", "-p");
1601 printf (" %s\n", "-b"); 2058 printf (" %s", _("number of packets to send (currently "));
1602 printf (" %s\n", _("Number of icmp data bytes to send")); 2059 printf ("%u)\n",packets);
1603 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN); 2060 printf (" %s\n", "-i");
1604 printf (" %s\n", "-v"); 2061 printf (" %s", _("max packet interval (currently "));
1605 printf (" %s\n", _("verbose")); 2062 printf ("%0.3fms)\n",(float)pkt_interval / 1000);
1606 2063 printf (" %s\n", "-I");
1607 printf ("\n"); 2064 printf (" %s", _("max target interval (currently "));
1608 printf ("%s\n", _("Notes:")); 2065 printf ("%0.3fms)\n", (float)target_interval / 1000);
1609 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not.")); 2066 printf (" %s\n", "-m");
1610 printf ("\n"); 2067 printf (" %s",_("number of alive hosts required for success"));
1611 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%")); 2068 printf ("\n");
1612 printf (" %s\n", _("packet loss. The default values should work well for most users.")); 2069 printf (" %s\n", "-l");
1613 printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations")); 2070 printf (" %s", _("TTL on outgoing packets (currently "));
1614 printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds.")); 2071 printf ("%u)\n", ttl);
1615/* -d not yet implemented */ 2072 printf (" %s\n", "-t");
1616/* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops")); 2073 printf (" %s",_("timeout value (seconds, currently "));
1617 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent.")); 2074 printf ("%u)\n", timeout);
1618 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/ 2075 printf (" %s\n", "-b");
1619 printf ("\n"); 2076 printf (" %s\n", _("Number of icmp data bytes to send"));
1620 printf (" %s\n", _("The -v switch can be specified several times for increased verbosity.")); 2077 printf (" %s %u + %d)\n", _("Packet size will be data bytes + icmp header (currently"),icmp_data_size, ICMP_MINLEN);
1621/* printf ("%s\n", _("Long options are currently unsupported.")); 2078 printf (" %s\n", "-v");
1622 printf ("%s\n", _("Options marked with * require an argument")); 2079 printf (" %s\n", _("verbose"));
1623*/ 2080 printf ("\n");
1624 2081 printf ("%s\n", _("Notes:"));
1625 printf (UT_SUPPORT); 2082 printf (" %s\n", _("If none of R,P,J,M,S or O is specified, default behavior is -R -P"));
2083 printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
2084 printf ("\n");
2085 printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
2086 printf (" %s\n", _("packet loss. The default values should work well for most users."));
2087 printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations"));
2088 printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds."));
2089 /* -d not yet implemented */
2090 /* printf ("%s\n", _("Threshold format for -d is warn,crit. 12,14 means WARNING if >= 12 hops"));
2091 printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent."));
2092 printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/
2093 printf ("\n");
2094 printf (" %s\n", _("The -v switch can be specified several times for increased verbosity."));
2095 /* printf ("%s\n", _("Long options are currently unsupported."));
2096 printf ("%s\n", _("Options marked with * require an argument"));
2097 */
2098
2099 printf (UT_SUPPORT);
1626} 2100}
1627 2101
1628 2102
@@ -1630,6 +2104,6 @@ print_help(void)
1630void 2104void
1631print_usage (void) 2105print_usage (void)
1632{ 2106{
1633 printf ("%s\n", _("Usage:")); 2107 printf ("%s\n", _("Usage:"));
1634 printf(" %s [options] [-H] host1 host2 hostN\n", progname); 2108 printf(" %s [options] [-H] host1 host2 hostN\n", progname);
1635} 2109}
diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t
index 96addd3..4f9db86 100644
--- a/plugins-root/t/check_icmp.t
+++ b/plugins-root/t/check_icmp.t
@@ -12,14 +12,14 @@ my $allow_sudo = getTestParameter( "NP_ALLOW_SUDO",
12 "no" ); 12 "no" );
13 13
14if ($allow_sudo eq "yes" or $> == 0) { 14if ($allow_sudo eq "yes" or $> == 0) {
15 plan tests => 20; 15 plan tests => 39;
16} else { 16} else {
17 plan skip_all => "Need sudo to test check_icmp"; 17 plan skip_all => "Need sudo to test check_icmp";
18} 18}
19my $sudo = $> == 0 ? '' : 'sudo'; 19my $sudo = $> == 0 ? '' : 'sudo';
20 20
21my $successOutput = '/OK - .*?: rta (?:[\d\.]+ms)|(?:nan), lost \d+%/'; 21my $successOutput = '/OK - .*? rta (?:[\d\.]+ms)|(?:nan), lost \d+%/';
22my $failureOutput = '/(WARNING|CRITICAL) - .*?: rta [\d\.]+ms, lost \d%/'; 22my $failureOutput = '/(WARNING|CRITICAL) - .*? rta (?:[\d\.]+ms > [\d\.]+ms|nan)/';
23 23
24my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE", 24my $host_responsive = getTestParameter( "NP_HOST_RESPONSIVE",
25 "The hostname of system responsive to network requests", 25 "The hostname of system responsive to network requests",
@@ -54,7 +54,7 @@ is( $res->return_code, 2, "Syntax ok, with forced critical" );
54like( $res->output, $failureOutput, "Output OK" ); 54like( $res->output, $failureOutput, "Output OK" );
55 55
56$res = NPTest->testCmd( 56$res = NPTest->testCmd(
57 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100%" 57 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -t 2"
58 ); 58 );
59is( $res->return_code, 2, "Timeout - host nonresponsive" ); 59is( $res->return_code, 2, "Timeout - host nonresponsive" );
60like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" ); 60like( $res->output, '/100%/', "Error contains '100%' string (for 100% packet loss)" );
@@ -66,13 +66,13 @@ is( $res->return_code, 3, "No hostname" );
66like( $res->output, '/No hosts to check/', "Output with appropriate error message"); 66like( $res->output, '/No hosts to check/', "Output with appropriate error message");
67 67
68$res = NPTest->testCmd( 68$res = NPTest->testCmd(
69 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0" 69 "$sudo ./check_icmp -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 0 -t 2"
70 ); 70 );
71is( $res->return_code, 0, "One host nonresponsive - zero required" ); 71is( $res->return_code, 0, "One host nonresponsive - zero required" );
72like( $res->output, $successOutput, "Output OK" ); 72like( $res->output, $successOutput, "Output OK" );
73 73
74$res = NPTest->testCmd( 74$res = NPTest->testCmd(
75 "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1" 75 "$sudo ./check_icmp -H $host_responsive -H $host_nonresponsive -w 10000ms,100% -c 10000ms,100% -n 1 -m 1 -t 2"
76 ); 76 );
77is( $res->return_code, 0, "One of two host nonresponsive - one required" ); 77is( $res->return_code, 0, "One of two host nonresponsive - one required" );
78like( $res->output, $successOutput, "Output OK" ); 78like( $res->output, $successOutput, "Output OK" );
@@ -94,3 +94,49 @@ $res = NPTest->testCmd(
94 ); 94 );
95is( $res->return_code, 0, "Try max packet size" ); 95is( $res->return_code, 0, "Try max packet size" );
96like( $res->output, $successOutput, "Output OK - Didn't overflow" ); 96like( $res->output, $successOutput, "Output OK - Didn't overflow" );
97
98$res = NPTest->testCmd(
99 "$sudo ./check_icmp -H $host_responsive -R 100,100 -n 1 -t 2"
100 );
101is( $res->return_code, 0, "rta works" );
102like( $res->output, $successOutput, "Output OK" );
103$res = NPTest->testCmd(
104 "$sudo ./check_icmp -H $host_responsive -P 80,90 -n 1 -t 2"
105 );
106is( $res->return_code, 0, "pl works" );
107like( $res->output, '/lost 0%/', "Output OK" );
108
109$res = NPTest->testCmd(
110 "$sudo ./check_icmp -H $host_responsive -J 80,90 -t 2"
111 );
112is( $res->return_code, 0, "jitter works" );
113like( $res->output, '/jitter \d/', "Output OK" );
114
115$res = NPTest->testCmd(
116 "$sudo ./check_icmp -H $host_responsive -M 4,3 -t 2"
117 );
118is( $res->return_code, 0, "mos works" );
119like( $res->output, '/MOS \d/', "Output OK" );
120
121$res = NPTest->testCmd(
122 "$sudo ./check_icmp -H $host_responsive -S 80,70 -t 2"
123 );
124is( $res->return_code, 0, "score works" );
125like( $res->output, '/Score \d/', "Output OK" );
126
127$res = NPTest->testCmd(
128 "$sudo ./check_icmp -H $host_responsive -O -t 2"
129 );
130is( $res->return_code, 0, "order works" );
131like( $res->output, '/Packets in order/', "Output OK" );
132
133$res = NPTest->testCmd(
134 "$sudo ./check_icmp -H $host_responsive -O -S 80,70 -M 4,3 -J 80,90 -P 80,90 -R 100,100 -t 2"
135 );
136is( $res->return_code, 0, "order works" );
137like( $res->output, '/Packets in order/', "Output OK" );
138like( $res->output, '/Score \d/', "Output OK" );
139like( $res->output, '/MOS \d/', "Output OK" );
140like( $res->output, '/jitter \d/', "Output OK" );
141like( $res->output, '/lost 0%/', "Output OK" );
142like( $res->output, $successOutput, "Output OK" );