summaryrefslogtreecommitdiffstats
path: root/plugins-root
diff options
context:
space:
mode:
Diffstat (limited to 'plugins-root')
-rw-r--r--plugins-root/Makefile.am5
-rw-r--r--plugins-root/check_dhcp.c699
-rw-r--r--plugins-root/check_icmp.c573
-rw-r--r--plugins-root/pst3.c2
-rw-r--r--plugins-root/t/check_dhcp.t9
-rw-r--r--plugins-root/t/check_icmp.t13
6 files changed, 763 insertions, 538 deletions
diff --git a/plugins-root/Makefile.am b/plugins-root/Makefile.am
index a1ebb6d2..40aa020d 100644
--- a/plugins-root/Makefile.am
+++ b/plugins-root/Makefile.am
@@ -26,7 +26,7 @@ EXTRA_PROGRAMS = pst3
26 26
27EXTRA_DIST = t pst3.c 27EXTRA_DIST = t pst3.c
28 28
29BASEOBJS = ../plugins/utils.o ../lib/libmonitoringplug.a ../gl/libgnu.a 29BASEOBJS = ../plugins/utils.o ../lib/libmonitoringplug.a ../gl/libgnu.a $(LIB_CRYPTO)
30NETOBJS = ../plugins/netutils.o $(BASEOBJS) $(EXTRA_NETOBJS) 30NETOBJS = ../plugins/netutils.o $(BASEOBJS) $(EXTRA_NETOBJS)
31NETLIBS = $(NETOBJS) $(SOCKETLIBS) 31NETLIBS = $(NETOBJS) $(SOCKETLIBS)
32 32
@@ -37,6 +37,9 @@ TESTS = @PLUGIN_TEST@
37test: 37test:
38 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl 38 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
39 39
40test-debug:
41 NPTEST_DEBUG=1 HARNESS_VERBOSE=1 perl -I $(top_builddir) -I $(top_srcdir) ../test.pl
42
40setuid_root_mode = ug=rx,u+s 43setuid_root_mode = ug=rx,u+s
41 44
42# /* Author Coreutils team - see ACKNOWLEDGEMENTS */ 45# /* Author Coreutils team - see ACKNOWLEDGEMENTS */
diff --git a/plugins-root/check_dhcp.c b/plugins-root/check_dhcp.c
index d8afb172..0ddace5b 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,39 @@ 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 */
159 struct dhcp_offer_struct *next; 153 struct dhcp_offer_struct *next;
160 }dhcp_offer; 154}dhcp_offer;
161 155
162 156
163typedef struct requested_server_struct{ 157typedef struct requested_server_struct{
164 struct in_addr server_address; 158 struct in_addr server_address;
165 int answered; 159 bool answered;
166 struct requested_server_struct *next; 160 struct requested_server_struct *next;
167 }requested_server; 161}requested_server;
168 162
169 163
170#define BOOTREQUEST 1 164#define BOOTREQUEST 1
@@ -198,7 +192,7 @@ typedef struct requested_server_struct{
198#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */ 192#define ETHERNET_HARDWARE_ADDRESS 1 /* used in htype field of dhcp packet */
199#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */ 193#define ETHERNET_HARDWARE_ADDRESS_LENGTH 6 /* length of Ethernet hardware addresses */
200 194
201u_int8_t unicast = 0; /* unicast mode: mimic a DHCP relay */ 195uint8_t unicast = 0; /* unicast mode: mimic a DHCP relay */
202struct in_addr my_ip; /* our address (required for relay) */ 196struct in_addr my_ip; /* our address (required for relay) */
203struct in_addr dhcp_ip; /* server to query (if in unicast mode) */ 197struct in_addr dhcp_ip; /* server to query (if in unicast mode) */
204unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]=""; 198unsigned char client_hardware_address[MAX_DHCP_CHADDR_LENGTH]="";
@@ -206,11 +200,11 @@ unsigned char *user_specified_mac=NULL;
206 200
207char network_interface_name[IFNAMSIZ]="eth0"; 201char network_interface_name[IFNAMSIZ]="eth0";
208 202
209u_int32_t packet_xid=0; 203uint32_t packet_xid=0;
210 204
211u_int32_t dhcp_lease_time=0; 205uint32_t dhcp_lease_time=0;
212u_int32_t dhcp_renewal_time=0; 206uint32_t dhcp_renewal_time=0;
213u_int32_t dhcp_rebinding_time=0; 207uint32_t dhcp_rebinding_time=0;
214 208
215int dhcpoffer_timeout=2; 209int dhcpoffer_timeout=2;
216 210
@@ -221,15 +215,15 @@ int valid_responses=0; /* number of valid DHCPOFFERs we received */
221int requested_servers=0; 215int requested_servers=0;
222int requested_responses=0; 216int requested_responses=0;
223 217
224int request_specific_address=FALSE; 218bool request_specific_address=false;
225int received_requested_address=FALSE; 219bool received_requested_address=false;
226int verbose=0; 220int verbose=0;
227struct in_addr requested_address; 221struct in_addr requested_address;
228 222
229 223
230int process_arguments(int, char **); 224int process_arguments(int, char **);
231int call_getopt(int, char **); 225int call_getopt(int, char **);
232int validate_arguments(int, int); 226int validate_arguments(int);
233void print_usage(void); 227void print_usage(void);
234void print_help(void); 228void print_help(void);
235 229
@@ -268,7 +262,7 @@ int main(int argc, char **argv){
268 262
269 if(process_arguments(argc,argv)!=OK){ 263 if(process_arguments(argc,argv)!=OK){
270 usage4 (_("Could not parse arguments")); 264 usage4 (_("Could not parse arguments"));
271 } 265 }
272 266
273 /* create socket for DHCP communications */ 267 /* create socket for DHCP communications */
274 dhcp_socket=create_dhcp_socket(); 268 dhcp_socket=create_dhcp_socket();
@@ -299,7 +293,7 @@ int main(int argc, char **argv){
299 free_requested_server_list(); 293 free_requested_server_list();
300 294
301 return result; 295 return result;
302 } 296}
303 297
304 298
305 299
@@ -314,82 +308,83 @@ int get_hardware_address(int sock,char *interface_name){
314 308
315 /* try and grab hardware address of requested interface */ 309 /* try and grab hardware address of requested interface */
316 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){ 310 if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0){
317 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name); 311 printf(_("Error: Could not get hardware address of interface '%s'\n"),interface_name);
318 exit(STATE_UNKNOWN); 312 exit(STATE_UNKNOWN);
319 } 313 }
320 314
321 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6); 315 memcpy(&client_hardware_address[0],&ifr.ifr_hwaddr.sa_data,6);
322 316
323#elif defined(__bsd__) 317#elif defined(__bsd__)
324 /* King 2004 see ACKNOWLEDGEMENTS */ 318 /* King 2004 see ACKNOWLEDGEMENTS */
325 319
326 int mib[6], len; 320 size_t len;
327 char *buf; 321 int mib[6];
328 unsigned char *ptr; 322 char *buf;
329 struct if_msghdr *ifm; 323 unsigned char *ptr;
330 struct sockaddr_dl *sdl; 324 struct if_msghdr *ifm;
331 325 struct sockaddr_dl *sdl;
332 mib[0] = CTL_NET; 326
333 mib[1] = AF_ROUTE; 327 mib[0] = CTL_NET;
334 mib[2] = 0; 328 mib[1] = AF_ROUTE;
335 mib[3] = AF_LINK; 329 mib[2] = 0;
336 mib[4] = NET_RT_IFLIST; 330 mib[3] = AF_LINK;
337 331 mib[4] = NET_RT_IFLIST;
338 if((mib[5] = if_nametoindex(interface_name)) == 0){ 332
339 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno)); 333 if((mib[5] = if_nametoindex(interface_name)) == 0){
340 exit(STATE_UNKNOWN); 334 printf(_("Error: if_nametoindex error - %s.\n"), strerror(errno));
341 } 335 exit(STATE_UNKNOWN);
336 }
342 337
343 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){ 338 if(sysctl(mib, 6, NULL, &len, NULL, 0) < 0){
344 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno)); 339 printf(_("Error: Couldn't get hardware address from %s. sysctl 1 error - %s.\n"), interface_name, strerror(errno));
345 exit(STATE_UNKNOWN); 340 exit(STATE_UNKNOWN);
346 } 341 }
347 342
348 if((buf = malloc(len)) == NULL){ 343 if((buf = malloc(len)) == NULL){
349 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno)); 344 printf(_("Error: Couldn't get hardware address from interface %s. malloc error - %s.\n"), interface_name, strerror(errno));
350 exit(4); 345 exit(4);
351 } 346 }
352 347
353 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){ 348 if(sysctl(mib, 6, buf, &len, NULL, 0) < 0){
354 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno)); 349 printf(_("Error: Couldn't get hardware address from %s. sysctl 2 error - %s.\n"), interface_name, strerror(errno));
355 exit(STATE_UNKNOWN); 350 exit(STATE_UNKNOWN);
356 } 351 }
357 352
358 ifm = (struct if_msghdr *)buf; 353 ifm = (struct if_msghdr *)buf;
359 sdl = (struct sockaddr_dl *)(ifm + 1); 354 sdl = (struct sockaddr_dl *)(ifm + 1);
360 ptr = (unsigned char *)LLADDR(sdl); 355 ptr = (unsigned char *)LLADDR(sdl);
361 memcpy(&client_hardware_address[0], ptr, 6) ; 356 memcpy(&client_hardware_address[0], ptr, 6) ;
362 /* King 2004 */ 357 /* King 2004 */
363 358
364#elif defined(__sun__) || defined(__solaris__) 359#elif defined(__sun__) || defined(__solaris__)
365 360
366 /* Kompf 2000-2003 see ACKNOWLEDGEMENTS */ 361 /* Kompf 2000-2003 see ACKNOWLEDGEMENTS */
367 long stat; 362 long stat;
368 char dev[20] = "/dev/"; 363 char dev[20] = "/dev/";
369 char *p; 364 char *p;
370 int unit; 365 int unit;
371 366
372 /* get last number from interfacename, eg lnc0, e1000g0*/ 367 /* get last number from interfacename, eg lnc0, e1000g0*/
373 int i; 368 int i;
374 p = interface_name + strlen(interface_name) -1; 369 p = interface_name + strlen(interface_name) -1;
375 for(i = strlen(interface_name) -1; i > 0; p--) { 370 for(i = strlen(interface_name) -1; i > 0; p--) {
376 if(isalpha(*p)) 371 if(isalpha(*p))
377 break; 372 break;
378 } 373 }
379 p++; 374 p++;
380 if( p != interface_name ){ 375 if( p != interface_name ){
381 unit = atoi(p) ; 376 unit = atoi(p) ;
382 strncat(dev, interface_name, 6) ; 377 strncat(dev, interface_name, 6) ;
383 } 378 }
384 else{ 379 else{
385 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name); 380 printf(_("Error: can't find unit number in interface_name (%s) - expecting TypeNumber eg lnc0.\n"), interface_name);
386 exit(STATE_UNKNOWN); 381 exit(STATE_UNKNOWN);
387 } 382 }
388 stat = mac_addr_dlpi(dev, unit, client_hardware_address); 383 stat = mac_addr_dlpi(dev, unit, client_hardware_address);
389 if(stat != 0){ 384 if(stat != 0){
390 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 385 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
391 exit(STATE_UNKNOWN); 386 exit(STATE_UNKNOWN);
392 } 387 }
393 388
394#elif defined(__hpux__) 389#elif defined(__hpux__)
395 390
@@ -401,8 +396,8 @@ int get_hardware_address(int sock,char *interface_name){
401 if(stat != 0){ 396 if(stat != 0){
402 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit); 397 printf(_("Error: can't read MAC address from DLPI streams interface for device %s unit %d.\n"), dev, unit);
403 exit(STATE_UNKNOWN); 398 exit(STATE_UNKNOWN);
404 } 399 }
405 /* Kompf 2000-2003 */ 400 /* Kompf 2000-2003 */
406 401
407#else 402#else
408 printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n")); 403 printf(_("Error: can't get MAC address for this architecture. Use the --mac option.\n"));
@@ -413,7 +408,7 @@ int get_hardware_address(int sock,char *interface_name){
413 print_hardware_address(client_hardware_address); 408 print_hardware_address(client_hardware_address);
414 409
415 return OK; 410 return OK;
416 } 411}
417 412
418/* determines IP address of the client interface */ 413/* determines IP address of the client interface */
419int get_ip_address(int sock,char *interface_name){ 414int get_ip_address(int sock,char *interface_name){
@@ -425,9 +420,9 @@ int get_ip_address(int sock,char *interface_name){
425 420
426 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){ 421 if(ioctl(sock,SIOCGIFADDR,&ifr)<0){
427 printf(_("Error: Cannot determine IP address of interface %s\n"), 422 printf(_("Error: Cannot determine IP address of interface %s\n"),
428 interface_name); 423 interface_name);
429 exit(STATE_UNKNOWN); 424 exit(STATE_UNKNOWN);
430 } 425 }
431 426
432 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; 427 my_ip=((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
433 428
@@ -440,13 +435,13 @@ int get_ip_address(int sock,char *interface_name){
440 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip)); 435 printf(_("Pretending to be relay client %s\n"),inet_ntoa(my_ip));
441 436
442 return OK; 437 return OK;
443 } 438}
444 439
445/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */ 440/* sends a DHCPDISCOVER broadcast message in an attempt to find DHCP servers */
446int send_dhcp_discover(int sock){ 441int send_dhcp_discover(int sock){
447 dhcp_packet discover_packet; 442 dhcp_packet discover_packet;
448 struct sockaddr_in sockaddr_broadcast; 443 struct sockaddr_in sockaddr_broadcast;
449 unsigned short opts; 444 unsigned short opts;
450 445
451 446
452 /* clear the packet data structure */ 447 /* clear the packet data structure */
@@ -463,17 +458,12 @@ int send_dhcp_discover(int sock){
463 discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH; 458 discover_packet.hlen=ETHERNET_HARDWARE_ADDRESS_LENGTH;
464 459
465 /* 460 /*
466 * transaction ID is supposed to be random. We won't use the address so 461 * transaction ID is supposed to be random.
467 * we don't care about high entropy here. time(2) is good enough.
468 */ 462 */
469 srand(time(NULL)); 463 srand(time(NULL)^getpid());
470 packet_xid=random(); 464 packet_xid=random();
471 discover_packet.xid=htonl(packet_xid); 465 discover_packet.xid=htonl(packet_xid);
472 466
473 /**** WHAT THE HECK IS UP WITH THIS?!? IF I DON'T MAKE THIS CALL, ONLY ONE SERVER RESPONSE IS PROCESSED!!!! ****/
474 /* downright bizzarre... */
475 ntohl(discover_packet.xid);
476
477 /*discover_packet.secs=htons(65535);*/ 467 /*discover_packet.secs=htons(65535);*/
478 discover_packet.secs=0xFF; 468 discover_packet.secs=0xFF;
479 469
@@ -492,19 +482,19 @@ int send_dhcp_discover(int sock){
492 discover_packet.options[2]='\x53'; 482 discover_packet.options[2]='\x53';
493 discover_packet.options[3]='\x63'; 483 discover_packet.options[3]='\x63';
494 484
495 opts = 4; 485 opts = 4;
496 /* DHCP message type is embedded in options field */ 486 /* DHCP message type is embedded in options field */
497 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */ 487 discover_packet.options[opts++]=DHCP_OPTION_MESSAGE_TYPE; /* DHCP message type option identifier */
498 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */ 488 discover_packet.options[opts++]='\x01'; /* DHCP message option length in bytes */
499 discover_packet.options[opts++]=DHCPDISCOVER; 489 discover_packet.options[opts++]=DHCPDISCOVER;
500 490
501 /* the IP address we're requesting */ 491 /* the IP address we're requesting */
502 if(request_specific_address==TRUE){ 492 if(request_specific_address){
503 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS; 493 discover_packet.options[opts++]=DHCP_OPTION_REQUESTED_ADDRESS;
504 discover_packet.options[opts++]='\x04'; 494 discover_packet.options[opts++]='\x04';
505 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address)); 495 memcpy(&discover_packet.options[opts],&requested_address,sizeof(requested_address));
506 opts += sizeof(requested_address); 496 opts += sizeof(requested_address);
507 } 497 }
508 discover_packet.options[opts++]=DHCP_OPTION_END; 498 discover_packet.options[opts++]=DHCP_OPTION_END;
509 499
510 /* unicast fields */ 500 /* unicast fields */
@@ -515,8 +505,8 @@ int send_dhcp_discover(int sock){
515 discover_packet.hops = unicast ? 1 : 0; 505 discover_packet.hops = unicast ? 1 : 0;
516 506
517 /* send the DHCPDISCOVER packet to broadcast address */ 507 /* send the DHCPDISCOVER packet to broadcast address */
518 sockaddr_broadcast.sin_family=AF_INET; 508 sockaddr_broadcast.sin_family=AF_INET;
519 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT); 509 sockaddr_broadcast.sin_port=htons(DHCP_SERVER_PORT);
520 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST; 510 sockaddr_broadcast.sin_addr.s_addr = unicast ? dhcp_ip.s_addr : INADDR_BROADCAST;
521 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero)); 511 bzero(&sockaddr_broadcast.sin_zero,sizeof(sockaddr_broadcast.sin_zero));
522 512
@@ -528,7 +518,7 @@ int send_dhcp_discover(int sock){
528 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr)); 518 printf("DHCDISCOVER yiaddr: %s\n",inet_ntoa(discover_packet.yiaddr));
529 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr)); 519 printf("DHCDISCOVER siaddr: %s\n",inet_ntoa(discover_packet.siaddr));
530 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr)); 520 printf("DHCDISCOVER giaddr: %s\n",inet_ntoa(discover_packet.giaddr));
531 } 521 }
532 522
533 /* send the DHCPDISCOVER packet out */ 523 /* send the DHCPDISCOVER packet out */
534 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast); 524 send_dhcp_packet(&discover_packet,sizeof(discover_packet),sock,&sockaddr_broadcast);
@@ -537,7 +527,7 @@ int send_dhcp_discover(int sock){
537 printf("\n\n"); 527 printf("\n\n");
538 528
539 return OK; 529 return OK;
540 } 530}
541 531
542 532
543 533
@@ -577,13 +567,13 @@ int get_dhcp_offer(int sock){
577 printf(_("Result=ERROR\n")); 567 printf(_("Result=ERROR\n"));
578 568
579 continue; 569 continue;
580 } 570 }
581 else{ 571 else{
582 if(verbose) 572 if(verbose)
583 printf(_("Result=OK\n")); 573 printf(_("Result=OK\n"));
584 574
585 responses++; 575 responses++;
586 } 576 }
587 577
588 /* The "source" is either a server or a relay. */ 578 /* The "source" is either a server or a relay. */
589 /* Save a copy of "source" into "via" even if it's via itself */ 579 /* Save a copy of "source" into "via" even if it's via itself */
@@ -593,7 +583,7 @@ int get_dhcp_offer(int sock){
593 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr)); 583 printf(_("DHCPOFFER from IP address %s"),inet_ntoa(source.sin_addr));
594 printf(_(" via %s\n"),inet_ntoa(via.sin_addr)); 584 printf(_(" via %s\n"),inet_ntoa(via.sin_addr));
595 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid)); 585 printf("DHCPOFFER XID: %u (0x%X)\n",ntohl(offer_packet.xid),ntohl(offer_packet.xid));
596 } 586 }
597 587
598 /* check packet xid to see if its the same as the one we used in the discover packet */ 588 /* check packet xid to see if its the same as the one we used in the discover packet */
599 if(ntohl(offer_packet.xid)!=packet_xid){ 589 if(ntohl(offer_packet.xid)!=packet_xid){
@@ -601,7 +591,7 @@ int get_dhcp_offer(int sock){
601 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid); 591 printf(_("DHCPOFFER XID (%u) did not match DHCPDISCOVER XID (%u) - ignoring packet\n"),ntohl(offer_packet.xid),packet_xid);
602 592
603 continue; 593 continue;
604 } 594 }
605 595
606 /* check hardware address */ 596 /* check hardware address */
607 result=OK; 597 result=OK;
@@ -614,7 +604,7 @@ int get_dhcp_offer(int sock){
614 604
615 if(offer_packet.chaddr[x]!=client_hardware_address[x]) 605 if(offer_packet.chaddr[x]!=client_hardware_address[x])
616 result=ERROR; 606 result=ERROR;
617 } 607 }
618 if(verbose) 608 if(verbose)
619 printf("\n"); 609 printf("\n");
620 610
@@ -623,27 +613,27 @@ int get_dhcp_offer(int sock){
623 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n")); 613 printf(_("DHCPOFFER hardware address did not match our own - ignoring packet\n"));
624 614
625 continue; 615 continue;
626 } 616 }
627 617
628 if(verbose){ 618 if(verbose){
629 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr)); 619 printf("DHCPOFFER ciaddr: %s\n",inet_ntoa(offer_packet.ciaddr));
630 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr)); 620 printf("DHCPOFFER yiaddr: %s\n",inet_ntoa(offer_packet.yiaddr));
631 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr)); 621 printf("DHCPOFFER siaddr: %s\n",inet_ntoa(offer_packet.siaddr));
632 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr)); 622 printf("DHCPOFFER giaddr: %s\n",inet_ntoa(offer_packet.giaddr));
633 } 623 }
634 624
635 add_dhcp_offer(source.sin_addr,&offer_packet); 625 add_dhcp_offer(source.sin_addr,&offer_packet);
636 626
637 valid_responses++; 627 valid_responses++;
638 } 628 }
639 629
640 if(verbose){ 630 if(verbose){
641 printf(_("Total responses seen on the wire: %d\n"),responses); 631 printf(_("Total responses seen on the wire: %d\n"),responses);
642 printf(_("Valid responses for this machine: %d\n"),valid_responses); 632 printf(_("Valid responses for this machine: %d\n"),valid_responses);
643 } 633 }
644 634
645 return OK; 635 return OK;
646 } 636}
647 637
648 638
649 639
@@ -660,14 +650,14 @@ int send_dhcp_packet(void *buffer, int buffer_size, int sock, struct sockaddr_in
660 return ERROR; 650 return ERROR;
661 651
662 return OK; 652 return OK;
663 } 653}
664 654
665 655
666 656
667/* receives a DHCP packet */ 657/* receives a DHCP packet */
668int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){ 658int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, struct sockaddr_in *address){
669 struct timeval tv; 659 struct timeval tv;
670 fd_set readfds; 660 fd_set readfds;
671 fd_set oobfds; 661 fd_set oobfds;
672 int recv_result; 662 int recv_result;
673 socklen_t address_size; 663 socklen_t address_size;
@@ -675,94 +665,88 @@ int receive_dhcp_packet(void *buffer, int buffer_size, int sock, int timeout, st
675 int nfound; 665 int nfound;
676 666
677 667
678 /* wait for data to arrive (up time timeout) */ 668 /* wait for data to arrive (up time timeout) */
679 tv.tv_sec=timeout; 669 tv.tv_sec=timeout;
680 tv.tv_usec=0; 670 tv.tv_usec=0;
681 FD_ZERO(&readfds); 671 FD_ZERO(&readfds);
682 FD_ZERO(&oobfds); 672 FD_ZERO(&oobfds);
683 FD_SET(sock,&readfds); 673 FD_SET(sock,&readfds);
684 FD_SET(sock,&oobfds); 674 FD_SET(sock,&oobfds);
685 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv); 675 nfound = select(sock+1,&readfds,NULL,&oobfds,&tv);
686 676
687 /* make sure some data has arrived */ 677 /* make sure some data has arrived */
688 if(!FD_ISSET(sock,&readfds)){ 678 if(!FD_ISSET(sock,&readfds)){
689 if(verbose) 679 if(verbose)
690 printf(_("No (more) data received (nfound: %d)\n"), nfound); 680 printf(_("No (more) data received (nfound: %d)\n"), nfound);
691 return ERROR; 681 return ERROR;
692 } 682 }
693
694 else{
695 683
696 /* why do we need to peek first? i don't know, its a hack. without it, the source address of the first packet received was 684 else{
697 not being interpreted correctly. sigh... */
698 bzero(&source_address,sizeof(source_address)); 685 bzero(&source_address,sizeof(source_address));
699 address_size=sizeof(source_address); 686 address_size=sizeof(source_address);
700 recv_result=recvfrom(sock,(char *)buffer,buffer_size,MSG_PEEK,(struct sockaddr *)&source_address,&address_size); 687 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size);
701 if(verbose) 688 if(verbose)
702 printf("recv_result_1: %d\n",recv_result); 689 printf("recv_result: %d\n",recv_result);
703 recv_result=recvfrom(sock,(char *)buffer,buffer_size,0,(struct sockaddr *)&source_address,&address_size);
704 if(verbose)
705 printf("recv_result_2: %d\n",recv_result);
706 690
707 if(recv_result==-1){ 691 if(recv_result==-1){
708 if(verbose){ 692 if(verbose){
709 printf(_("recvfrom() failed, ")); 693 printf(_("recvfrom() failed, "));
710 printf("errno: (%d) -> %s\n",errno,strerror(errno)); 694 printf("errno: (%d) -> %s\n",errno,strerror(errno));
711 } 695 }
712 return ERROR; 696 return ERROR;
713 } 697 }
714 else{ 698 else{
715 if(verbose){ 699 if(verbose){
716 printf(_("receive_dhcp_packet() result: %d\n"),recv_result); 700 printf(_("receive_dhcp_packet() result: %d\n"),recv_result);
717 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr)); 701 printf(_("receive_dhcp_packet() source: %s\n"),inet_ntoa(source_address.sin_addr));
718 } 702 }
719 703
720 memcpy(address,&source_address,sizeof(source_address)); 704 memcpy(address,&source_address,sizeof(source_address));
721 return OK; 705 return OK;
722 } 706 }
723 } 707 }
724 708
725 return OK; 709 return OK;
726 } 710}
727 711
728 712
729/* creates a socket for DHCP communication */ 713/* creates a socket for DHCP communication */
730int create_dhcp_socket(void){ 714int create_dhcp_socket(void){
731 struct sockaddr_in myname; 715 struct sockaddr_in myname;
732 struct ifreq interface; 716 struct ifreq interface;
733 int sock; 717 int sock;
734 int flag=1; 718 int flag=1;
735 719
736 /* Set up the address we're going to bind to. */ 720 /* Set up the address we're going to bind to. */
737 bzero(&myname,sizeof(myname)); 721 bzero(&myname,sizeof(myname));
738 myname.sin_family=AF_INET; 722 myname.sin_family=AF_INET;
739 /* listen to DHCP server port if we're in unicast mode */ 723 /* listen to DHCP server port if we're in unicast mode */
740 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT); 724 myname.sin_port = htons(unicast ? DHCP_SERVER_PORT : DHCP_CLIENT_PORT);
741 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY; 725 myname.sin_addr.s_addr = unicast ? my_ip.s_addr : INADDR_ANY;
742 bzero(&myname.sin_zero,sizeof(myname.sin_zero)); 726 bzero(&myname.sin_zero,sizeof(myname.sin_zero));
743 727
744 /* create a socket for DHCP communications */ 728 /* create a socket for DHCP communications */
745 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); 729 sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
746 if(sock<0){ 730 if(sock<0){
747 printf(_("Error: Could not create socket!\n")); 731 printf(_("Error: Could not create socket!\n"));
748 exit(STATE_UNKNOWN); 732 exit(STATE_UNKNOWN);
749 } 733 }
750 734
751 if(verbose) 735 if(verbose)
752 printf("DHCP socket: %d\n",sock); 736 printf("DHCP socket: %d\n",sock);
753 737
754 /* set the reuse address flag so we don't get errors when restarting */ 738 /* set the reuse address flag so we don't get errors when restarting */
755 flag=1; 739 flag=1;
756 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){ 740 if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&flag,sizeof(flag))<0){
757 printf(_("Error: Could not set reuse address option on DHCP socket!\n")); 741 printf(_("Error: Could not set reuse address option on DHCP socket!\n"));
758 exit(STATE_UNKNOWN); 742 exit(STATE_UNKNOWN);
759 } 743 }
760 744
761 /* set the broadcast option - we need this to listen to DHCP broadcast messages */ 745 /* set the broadcast option - we need this to listen to DHCP broadcast messages */
762 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){ 746 if(!unicast && setsockopt(sock,SOL_SOCKET,SO_BROADCAST,(char *)&flag,sizeof flag)<0){
763 printf(_("Error: Could not set broadcast option on DHCP socket!\n")); 747 printf(_("Error: Could not set broadcast option on DHCP socket!\n"));
764 exit(STATE_UNKNOWN); 748 exit(STATE_UNKNOWN);
765 } 749 }
766 750
767 /* bind socket to interface */ 751 /* bind socket to interface */
768#if defined(__linux__) 752#if defined(__linux__)
@@ -771,21 +755,21 @@ int create_dhcp_socket(void){
771 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){ 755 if(setsockopt(sock,SOL_SOCKET,SO_BINDTODEVICE,(char *)&interface,sizeof(interface))<0){
772 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name); 756 printf(_("Error: Could not bind socket to interface %s. Check your privileges...\n"),network_interface_name);
773 exit(STATE_UNKNOWN); 757 exit(STATE_UNKNOWN);
774 } 758 }
775 759
776#else 760#else
777 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1); 761 strncpy(interface.ifr_name,network_interface_name,IFNAMSIZ-1);
778 interface.ifr_name[IFNAMSIZ-1]='\0'; 762 interface.ifr_name[IFNAMSIZ-1]='\0';
779#endif 763#endif
780 764
781 /* bind the socket */ 765 /* bind the socket */
782 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){ 766 if(bind(sock,(struct sockaddr *)&myname,sizeof(myname))<0){
783 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT); 767 printf(_("Error: Could not bind to DHCP socket (port %d)! Check your privileges...\n"),DHCP_CLIENT_PORT);
784 exit(STATE_UNKNOWN); 768 exit(STATE_UNKNOWN);
785 } 769 }
786 770
787 return sock; 771 return sock;
788 } 772}
789 773
790 774
791/* closes DHCP socket */ 775/* closes DHCP socket */
@@ -794,7 +778,7 @@ int close_dhcp_socket(int sock){
794 close(sock); 778 close(sock);
795 779
796 return OK; 780 return OK;
797 } 781}
798 782
799 783
800/* adds a requested server address to list in memory */ 784/* adds a requested server address to list in memory */
@@ -806,7 +790,7 @@ int add_requested_server(struct in_addr server_address){
806 return ERROR; 790 return ERROR;
807 791
808 new_server->server_address=server_address; 792 new_server->server_address=server_address;
809 new_server->answered=FALSE; 793 new_server->answered=false;
810 794
811 new_server->next=requested_server_list; 795 new_server->next=requested_server_list;
812 requested_server_list=new_server; 796 requested_server_list=new_server;
@@ -817,7 +801,7 @@ int add_requested_server(struct in_addr server_address){
817 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address)); 801 printf(_("Requested server address: %s\n"),inet_ntoa(new_server->server_address));
818 802
819 return OK; 803 return OK;
820 } 804}
821 805
822 806
823 807
@@ -850,29 +834,29 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
850 834
851 /* get option data */ 835 /* get option data */
852 switch(option_type){ 836 switch(option_type){
853 case DHCP_OPTION_LEASE_TIME: 837 case DHCP_OPTION_LEASE_TIME:
854 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time)); 838 memcpy(&dhcp_lease_time, &offer_packet->options[x],sizeof(dhcp_lease_time));
855 dhcp_lease_time = ntohl(dhcp_lease_time); 839 dhcp_lease_time = ntohl(dhcp_lease_time);
856 break; 840 break;
857 case DHCP_OPTION_RENEWAL_TIME: 841 case DHCP_OPTION_RENEWAL_TIME:
858 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time)); 842 memcpy(&dhcp_renewal_time, &offer_packet->options[x],sizeof(dhcp_renewal_time));
859 dhcp_renewal_time = ntohl(dhcp_renewal_time); 843 dhcp_renewal_time = ntohl(dhcp_renewal_time);
860 break; 844 break;
861 case DHCP_OPTION_REBINDING_TIME: 845 case DHCP_OPTION_REBINDING_TIME:
862 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time)); 846 memcpy(&dhcp_rebinding_time, &offer_packet->options[x],sizeof(dhcp_rebinding_time));
863 dhcp_rebinding_time = ntohl(dhcp_rebinding_time); 847 dhcp_rebinding_time = ntohl(dhcp_rebinding_time);
864 break; 848 break;
865 case DHCP_OPTION_SERVER_IDENTIFIER: 849 case DHCP_OPTION_SERVER_IDENTIFIER:
866 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr)); 850 memcpy(&serv_ident.s_addr, &offer_packet->options[x],sizeof(serv_ident.s_addr));
867 break; 851 break;
868 } 852 }
869 853
870 /* skip option data we're ignoring */ 854 /* skip option data we're ignoring */
871 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */ 855 if(option_type==0) /* "pad" option, see RFC 2132 (3.1) */
872 x+=1; 856 x+=1;
873 else 857 else
874 x+=option_length; 858 x+=option_length;
875 } 859 }
876 860
877 if(verbose){ 861 if(verbose){
878 if(dhcp_lease_time==DHCP_INFINITE_TIME) 862 if(dhcp_lease_time==DHCP_INFINITE_TIME)
@@ -886,7 +870,7 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
886 if(dhcp_rebinding_time==DHCP_INFINITE_TIME) 870 if(dhcp_rebinding_time==DHCP_INFINITE_TIME)
887 printf(_("Rebinding Time: Infinite\n")); 871 printf(_("Rebinding Time: Infinite\n"));
888 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time); 872 printf(_("Rebinding Time: %lu seconds\n"),(unsigned long)dhcp_rebinding_time);
889 } 873 }
890 874
891 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer)); 875 new_offer=(dhcp_offer *)malloc(sizeof(dhcp_offer));
892 876
@@ -915,14 +899,14 @@ int add_dhcp_offer(struct in_addr source,dhcp_packet *offer_packet){
915 if(verbose){ 899 if(verbose){
916 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address)); 900 printf(_("Added offer from server @ %s"),inet_ntoa(new_offer->server_address));
917 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address)); 901 printf(_(" of IP address %s\n"),inet_ntoa(new_offer->offered_address));
918 } 902 }
919 903
920 /* add new offer to head of list */ 904 /* add new offer to head of list */
921 new_offer->next=dhcp_offer_list; 905 new_offer->next=dhcp_offer_list;
922 dhcp_offer_list=new_offer; 906 dhcp_offer_list=new_offer;
923 907
924 return OK; 908 return OK;
925 } 909}
926 910
927 911
928/* frees memory allocated to DHCP OFFER list */ 912/* frees memory allocated to DHCP OFFER list */
@@ -933,10 +917,10 @@ int free_dhcp_offer_list(void){
933 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){ 917 for(this_offer=dhcp_offer_list;this_offer!=NULL;this_offer=next_offer){
934 next_offer=this_offer->next; 918 next_offer=this_offer->next;
935 free(this_offer); 919 free(this_offer);
936 } 920 }
937 921
938 return OK; 922 return OK;
939 } 923}
940 924
941 925
942/* frees memory allocated to requested server list */ 926/* frees memory allocated to requested server list */
@@ -947,10 +931,10 @@ int free_requested_server_list(void){
947 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){ 931 for(this_server=requested_server_list;this_server!=NULL;this_server=next_server){
948 next_server=this_server->next; 932 next_server=this_server->next;
949 free(this_server); 933 free(this_server);
950 } 934 }
951 935
952 return OK; 936 return OK;
953 } 937}
954 938
955 939
956/* gets state and plugin output to return */ 940/* gets state and plugin output to return */
@@ -958,9 +942,9 @@ int get_results(void){
958 dhcp_offer *temp_offer; 942 dhcp_offer *temp_offer;
959 requested_server *temp_server; 943 requested_server *temp_server;
960 int result; 944 int result;
961 u_int32_t max_lease_time=0; 945 uint32_t max_lease_time=0;
962 946
963 received_requested_address=FALSE; 947 received_requested_address=false;
964 948
965 /* checks responses from requested servers */ 949 /* checks responses from requested servers */
966 requested_responses=0; 950 requested_responses=0;
@@ -976,7 +960,7 @@ int get_results(void){
976 960
977 /* see if we got the address we requested */ 961 /* see if we got the address we requested */
978 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 962 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
979 received_requested_address=TRUE; 963 received_requested_address=true;
980 964
981 /* see if the servers we wanted a response from talked to us or not */ 965 /* see if the servers we wanted a response from talked to us or not */
982 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){ 966 if(!memcmp(&temp_offer->server_address,&temp_server->server_address,sizeof(temp_server->server_address))){
@@ -986,16 +970,16 @@ int get_results(void){
986 if(temp_server->answered) 970 if(temp_server->answered)
987 printf(_(" (duplicate)")); 971 printf(_(" (duplicate)"));
988 printf(_("\n")); 972 printf(_("\n"));
989 } 973 }
990 if(temp_server->answered == FALSE){ 974 if(!temp_server->answered){
991 requested_responses++; 975 requested_responses++;
992 temp_server->answered=TRUE; 976 temp_server->answered=true;
993 } 977 }
994 } 978 }
995 } 979 }
996 } 980 }
997 981
998 } 982 }
999 983
1000 /* else check and see if we got our requested address from any server */ 984 /* else check and see if we got our requested address from any server */
1001 else{ 985 else{
@@ -1008,9 +992,9 @@ int get_results(void){
1008 992
1009 /* see if we got the address we requested */ 993 /* see if we got the address we requested */
1010 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address))) 994 if(!memcmp(&requested_address,&temp_offer->offered_address,sizeof(requested_address)))
1011 received_requested_address=TRUE; 995 received_requested_address=true;
1012 } 996 }
1013 } 997 }
1014 998
1015 result=STATE_OK; 999 result=STATE_OK;
1016 if(valid_responses==0) 1000 if(valid_responses==0)
@@ -1019,7 +1003,7 @@ int get_results(void){
1019 result=STATE_CRITICAL; 1003 result=STATE_CRITICAL;
1020 else if(requested_responses<requested_servers) 1004 else if(requested_responses<requested_servers)
1021 result=STATE_WARNING; 1005 result=STATE_WARNING;
1022 else if(request_specific_address==TRUE && received_requested_address==FALSE) 1006 else if(request_specific_address && !received_requested_address)
1023 result=STATE_WARNING; 1007 result=STATE_WARNING;
1024 1008
1025 if(result==0) /* garrett honeycutt 2005 */ 1009 if(result==0) /* garrett honeycutt 2005 */
@@ -1035,15 +1019,15 @@ int get_results(void){
1035 if(dhcp_offer_list==NULL){ 1019 if(dhcp_offer_list==NULL){
1036 printf(_("No DHCPOFFERs were received.\n")); 1020 printf(_("No DHCPOFFERs were received.\n"));
1037 return result; 1021 return result;
1038 } 1022 }
1039 1023
1040 printf(_("Received %d DHCPOFFER(s)"),valid_responses); 1024 printf(_("Received %d DHCPOFFER(s)"),valid_responses);
1041 1025
1042 if(requested_servers>0) 1026 if(requested_servers>0)
1043 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers); 1027 printf(_(", %s%d of %d requested servers responded"),((requested_responses<requested_servers) && requested_responses>0)?"only ":"",requested_responses,requested_servers);
1044 1028
1045 if(request_specific_address==TRUE) 1029 if(request_specific_address)
1046 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address==TRUE)?"":_("not ")); 1030 printf(_(", requested address (%s) was %soffered"),inet_ntoa(requested_address),(received_requested_address)?"":_("not "));
1047 1031
1048 printf(_(", max lease time = ")); 1032 printf(_(", max lease time = "));
1049 if(max_lease_time==DHCP_INFINITE_TIME) 1033 if(max_lease_time==DHCP_INFINITE_TIME)
@@ -1054,7 +1038,7 @@ int get_results(void){
1054 printf(".\n"); 1038 printf(".\n");
1055 1039
1056 return result; 1040 return result;
1057 } 1041}
1058 1042
1059 1043
1060/* process command-line arguments */ 1044/* process command-line arguments */
@@ -1065,8 +1049,8 @@ int process_arguments(int argc, char **argv){
1065 return ERROR; 1049 return ERROR;
1066 1050
1067 arg_index = call_getopt(argc,argv); 1051 arg_index = call_getopt(argc,argv);
1068 return validate_arguments(argc,arg_index); 1052 return validate_arguments(argc);
1069 } 1053}
1070 1054
1071 1055
1072 1056
@@ -1097,80 +1081,80 @@ int call_getopt(int argc, char **argv){
1097 1081
1098 switch(c){ 1082 switch(c){
1099 1083
1100 case 's': /* DHCP server address */ 1084 case 's': /* DHCP server address */
1101 resolve_host(optarg,&dhcp_ip); 1085 resolve_host(optarg,&dhcp_ip);
1102 add_requested_server(dhcp_ip); 1086 add_requested_server(dhcp_ip);
1103 break; 1087 break;
1104 1088
1105 case 'r': /* address we are requested from DHCP servers */ 1089 case 'r': /* address we are requested from DHCP servers */
1106 resolve_host(optarg,&requested_address); 1090 resolve_host(optarg,&requested_address);
1107 request_specific_address=TRUE; 1091 request_specific_address=true;
1108 break; 1092 break;
1109 1093
1110 case 't': /* timeout */ 1094 case 't': /* timeout */
1111
1112 /*
1113 if(is_intnonneg(optarg))
1114 */
1115 if(atoi(optarg)>0)
1116 dhcpoffer_timeout=atoi(optarg);
1117 /*
1118 else
1119 usage("Time interval must be a nonnegative integer\n");
1120 */
1121 break;
1122 1095
1123 case 'm': /* MAC address */ 1096 /*
1097 if(is_intnonneg(optarg))
1098 */
1099 if(atoi(optarg)>0)
1100 dhcpoffer_timeout=atoi(optarg);
1101 /*
1102 else
1103 usage("Time interval must be a nonnegative integer\n");
1104 */
1105 break;
1124 1106
1125 if((user_specified_mac=mac_aton(optarg)) == NULL) 1107 case 'm': /* MAC address */
1126 usage("Cannot parse MAC address.\n");
1127 if(verbose)
1128 print_hardware_address(user_specified_mac);
1129 1108
1130 break; 1109 if((user_specified_mac=mac_aton(optarg)) == NULL)
1110 usage("Cannot parse MAC address.\n");
1111 if(verbose)
1112 print_hardware_address(user_specified_mac);
1131 1113
1132 case 'i': /* interface name */ 1114 break;
1133 1115
1134 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1); 1116 case 'i': /* interface name */
1135 network_interface_name[sizeof(network_interface_name)-1]='\x0';
1136 1117
1137 break; 1118 strncpy(network_interface_name,optarg,sizeof(network_interface_name)-1);
1119 network_interface_name[sizeof(network_interface_name)-1]='\x0';
1138 1120
1139 case 'u': /* unicast testing */ 1121 break;
1140 unicast=1;
1141 break;
1142 1122
1143 case 'V': /* version */ 1123 case 'u': /* unicast testing */
1144 print_revision(progname, NP_VERSION); 1124 unicast=1;
1145 exit(STATE_UNKNOWN); 1125 break;
1146 1126
1147 case 'h': /* help */ 1127 case 'V': /* version */
1148 print_help(); 1128 print_revision(progname, NP_VERSION);
1149 exit(STATE_UNKNOWN); 1129 exit(STATE_UNKNOWN);
1150 1130
1151 case 'v': /* verbose */ 1131 case 'h': /* help */
1152 verbose=1; 1132 print_help();
1153 break; 1133 exit(STATE_UNKNOWN);
1154 1134
1155 case '?': /* help */ 1135 case 'v': /* verbose */
1156 usage5 (); 1136 verbose=1;
1157 break; 1137 break;
1158 1138
1159 default: 1139 case '?': /* help */
1160 break; 1140 usage5 ();
1161 } 1141 break;
1162 } 1142
1143 default:
1144 break;
1145 }
1146 }
1163 return optind; 1147 return optind;
1164 } 1148}
1165 1149
1166 1150
1167int validate_arguments(int argc, int arg_index){ 1151int validate_arguments(int argc){
1168 1152
1169 if(argc-optind > 0) 1153 if(argc - optind > 0)
1170 usage(_("Got unexpected non-option argument")); 1154 usage(_("Got unexpected non-option argument"));
1171 1155
1172 return OK; 1156 return OK;
1173 } 1157}
1174 1158
1175 1159
1176#if defined(__sun__) || defined(__solaris__) || defined(__hpux__) 1160#if defined(__sun__) || defined(__solaris__) || defined(__hpux__)
@@ -1188,21 +1172,21 @@ static int get_msg(int fd){
1188 if(res < 0){ 1172 if(res < 0){
1189 if(errno == EINTR){ 1173 if(errno == EINTR){
1190 return(GOT_INTR); 1174 return(GOT_INTR);
1191 } 1175 }
1192 else{ 1176 else{
1193 printf("%s\n", "get_msg FAILED."); 1177 printf("%s\n", "get_msg FAILED.");
1194 return(GOT_ERR); 1178 return(GOT_ERR);
1195 }
1196 } 1179 }
1180 }
1197 if(ctl.len > 0){ 1181 if(ctl.len > 0){
1198 ret |= GOT_CTRL; 1182 ret |= GOT_CTRL;
1199 } 1183 }
1200 if(dat.len > 0){ 1184 if(dat.len > 0){
1201 ret |= GOT_DATA; 1185 ret |= GOT_DATA;
1202 } 1186 }
1203 1187
1204 return(ret); 1188 return(ret);
1205 } 1189}
1206 1190
1207/* verify that dl_primitive in ctl_area = prim */ 1191/* verify that dl_primitive in ctl_area = prim */
1208static int check_ctrl(int prim){ 1192static int check_ctrl(int prim){
@@ -1211,10 +1195,10 @@ static int check_ctrl(int prim){
1211 if(err_ack->dl_primitive != prim){ 1195 if(err_ack->dl_primitive != prim){
1212 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno)); 1196 printf(_("Error: DLPI stream API failed to get MAC in check_ctrl: %s.\n"), strerror(errno));
1213 exit(STATE_UNKNOWN); 1197 exit(STATE_UNKNOWN);
1214 } 1198 }
1215 1199
1216 return 0; 1200 return 0;
1217 } 1201}
1218 1202
1219/* put a control message on a stream */ 1203/* put a control message on a stream */
1220static int put_ctrl(int fd, int len, int pri){ 1204static int put_ctrl(int fd, int len, int pri){
@@ -1223,10 +1207,10 @@ static int put_ctrl(int fd, int len, int pri){
1223 if(putmsg(fd, &ctl, 0, pri) < 0){ 1207 if(putmsg(fd, &ctl, 0, pri) < 0){
1224 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno)); 1208 printf(_("Error: DLPI stream API failed to get MAC in put_ctrl/putmsg(): %s.\n"), strerror(errno));
1225 exit(STATE_UNKNOWN); 1209 exit(STATE_UNKNOWN);
1226 } 1210 }
1227 1211
1228 return 0; 1212 return 0;
1229 } 1213}
1230 1214
1231/* put a control + data message on a stream */ 1215/* put a control + data message on a stream */
1232static int put_both(int fd, int clen, int dlen, int pri){ 1216static int put_both(int fd, int clen, int dlen, int pri){
@@ -1236,10 +1220,10 @@ static int put_both(int fd, int clen, int dlen, int pri){
1236 if(putmsg(fd, &ctl, &dat, pri) < 0){ 1220 if(putmsg(fd, &ctl, &dat, pri) < 0){
1237 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno)); 1221 printf(_("Error: DLPI stream API failed to get MAC in put_both/putmsg().\n"), strerror(errno));
1238 exit(STATE_UNKNOWN); 1222 exit(STATE_UNKNOWN);
1239 } 1223 }
1240 1224
1241 return 0; 1225 return 0;
1242 } 1226}
1243 1227
1244/* open file descriptor and attach */ 1228/* open file descriptor and attach */
1245static int dl_open(const char *dev, int unit, int *fd){ 1229static int dl_open(const char *dev, int unit, int *fd){
@@ -1248,13 +1232,13 @@ static int dl_open(const char *dev, int unit, int *fd){
1248 if((*fd = open(dev, O_RDWR)) == -1){ 1232 if((*fd = open(dev, O_RDWR)) == -1){
1249 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno)); 1233 printf(_("Error: DLPI stream API failed to get MAC in dl_attach_req/open(%s..): %s.\n"), dev, strerror(errno));
1250 exit(STATE_UNKNOWN); 1234 exit(STATE_UNKNOWN);
1251 } 1235 }
1252 attach_req->dl_primitive = DL_ATTACH_REQ; 1236 attach_req->dl_primitive = DL_ATTACH_REQ;
1253 attach_req->dl_ppa = unit; 1237 attach_req->dl_ppa = unit;
1254 put_ctrl(*fd, sizeof(dl_attach_req_t), 0); 1238 put_ctrl(*fd, sizeof(dl_attach_req_t), 0);
1255 get_msg(*fd); 1239 get_msg(*fd);
1256 return check_ctrl(DL_OK_ACK); 1240 return check_ctrl(DL_OK_ACK);
1257 } 1241}
1258 1242
1259/* send DL_BIND_REQ */ 1243/* send DL_BIND_REQ */
1260static int dl_bind(int fd, int sap, u_char *addr){ 1244static int dl_bind(int fd, int sap, u_char *addr){
@@ -1272,12 +1256,12 @@ static int dl_bind(int fd, int sap, u_char *addr){
1272 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){ 1256 if (GOT_ERR == check_ctrl(DL_BIND_ACK)){
1273 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno)); 1257 printf(_("Error: DLPI stream API failed to get MAC in dl_bind/check_ctrl(): %s.\n"), strerror(errno));
1274 exit(STATE_UNKNOWN); 1258 exit(STATE_UNKNOWN);
1275 } 1259 }
1276 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr, 1260 bcopy((u_char *)bind_ack + bind_ack->dl_addr_offset, addr,
1277 bind_ack->dl_addr_length); 1261 bind_ack->dl_addr_length);
1278 1262
1279 return 0; 1263 return 0;
1280 } 1264}
1281 1265
1282/*********************************************************************** 1266/***********************************************************************
1283 * interface: 1267 * interface:
@@ -1296,15 +1280,15 @@ long mac_addr_dlpi( const char *dev, int unit, u_char *addr){
1296 u_char mac_addr[25]; 1280 u_char mac_addr[25];
1297 1281
1298 if(GOT_ERR != dl_open(dev, unit, &fd)){ 1282 if(GOT_ERR != dl_open(dev, unit, &fd)){
1299 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){ 1283 if(GOT_ERR != dl_bind(fd, INSAP, mac_addr)){
1300 bcopy( mac_addr, addr, 6); 1284 bcopy( mac_addr, addr, 6);
1301 return 0; 1285 return 0;
1302 }
1303 } 1286 }
1304 close(fd); 1287 }
1288 close(fd);
1305 1289
1306 return -1; 1290 return -1;
1307 } 1291}
1308 1292
1309/* Kompf 2000-2003 */ 1293/* Kompf 2000-2003 */
1310#endif 1294#endif
@@ -1321,7 +1305,7 @@ void resolve_host(const char *in,struct in_addr *out){
1321 1305
1322 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out)); 1306 memcpy(out,&((struct sockaddr_in *)ai->ai_addr)->sin_addr,sizeof(*out));
1323 freeaddrinfo(ai); 1307 freeaddrinfo(ai);
1324 } 1308}
1325 1309
1326 1310
1327/* parse MAC address string, return 6 bytes (unterminated) or NULL */ 1311/* parse MAC address string, return 6 bytes (unterminated) or NULL */
@@ -1340,10 +1324,10 @@ unsigned char *mac_aton(const char *string){
1340 result[j]=strtol(tmp,(char **)NULL,16); 1324 result[j]=strtol(tmp,(char **)NULL,16);
1341 i++; 1325 i++;
1342 j++; 1326 j++;
1343 } 1327 }
1344 1328
1345 return (j==6) ? result : NULL; 1329 return (j==6) ? result : NULL;
1346 } 1330}
1347 1331
1348 1332
1349void print_hardware_address(const unsigned char *address){ 1333void print_hardware_address(const unsigned char *address){
@@ -1354,7 +1338,7 @@ void print_hardware_address(const unsigned char *address){
1354 printf("%2.2x:", address[i]); 1338 printf("%2.2x:", address[i]);
1355 printf("%2.2x", address[i]); 1339 printf("%2.2x", address[i]);
1356 putchar('\n'); 1340 putchar('\n');
1357 } 1341}
1358 1342
1359 1343
1360/* print usage help */ 1344/* print usage help */
@@ -1367,7 +1351,7 @@ void print_help(void){
1367 1351
1368 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network.")); 1352 printf("%s\n", _("This plugin tests the availability of DHCP servers on a network."));
1369 1353
1370 printf ("\n\n"); 1354 printf ("\n\n");
1371 1355
1372 print_usage(); 1356 print_usage();
1373 1357
@@ -1377,32 +1361,29 @@ void print_help(void){
1377 printf (UT_VERBOSE); 1361 printf (UT_VERBOSE);
1378 1362
1379 printf (" %s\n", "-s, --serverip=IPADDRESS"); 1363 printf (" %s\n", "-s, --serverip=IPADDRESS");
1380 printf (" %s\n", _("IP address of DHCP server that we must hear from")); 1364 printf (" %s\n", _("IP address of DHCP server that we must hear from"));
1381 printf (" %s\n", "-r, --requestedip=IPADDRESS"); 1365 printf (" %s\n", "-r, --requestedip=IPADDRESS");
1382 printf (" %s\n", _("IP address that should be offered by at least one DHCP server")); 1366 printf (" %s\n", _("IP address that should be offered by at least one DHCP server"));
1383 printf (" %s\n", "-t, --timeout=INTEGER"); 1367 printf (" %s\n", "-t, --timeout=INTEGER");
1384 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs")); 1368 printf (" %s\n", _("Seconds to wait for DHCPOFFER before timeout occurs"));
1385 printf (" %s\n", "-i, --interface=STRING"); 1369 printf (" %s\n", "-i, --interface=STRING");
1386 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)")); 1370 printf (" %s\n", _("Interface to to use for listening (i.e. eth0)"));
1387 printf (" %s\n", "-m, --mac=STRING"); 1371 printf (" %s\n", "-m, --mac=STRING");
1388 printf (" %s\n", _("MAC address to use in the DHCP request")); 1372 printf (" %s\n", _("MAC address to use in the DHCP request"));
1389 printf (" %s\n", "-u, --unicast"); 1373 printf (" %s\n", "-u, --unicast");
1390 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s")); 1374 printf (" %s\n", _("Unicast testing: mimic a DHCP relay, requires -s"));
1391 1375
1392 printf (UT_SUPPORT); 1376 printf (UT_SUPPORT);
1393 return; 1377 return;
1394 } 1378}
1395 1379
1396 1380
1397void 1381void
1398print_usage(void){ 1382print_usage(void){
1399 1383
1400 printf ("%s\n", _("Usage:")); 1384 printf ("%s\n", _("Usage:"));
1401 printf (" %s [-v] [-u] [-s serverip] [-r requestedip] [-t timeout]\n",progname); 1385 printf (" %s [-v] [-u] [-s serverip] [-r requestedip] [-t timeout]\n",progname);
1402 printf (" [-i interface] [-m mac]\n"); 1386 printf (" [-i interface] [-m mac]\n");
1403 1387
1404 return; 1388 return;
1405 } 1389}
1406
1407
1408
diff --git a/plugins-root/check_icmp.c b/plugins-root/check_icmp.c
index 9ed12ba1..1d47e9fc 100644
--- a/plugins-root/check_icmp.c
+++ b/plugins-root/check_icmp.c
@@ -1,39 +1,39 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2*
3* Monitoring check_icmp plugin 3* Monitoring check_icmp plugin
4* 4*
5* License: GPL 5* License: GPL
6* Copyright (c) 2005-2008 Monitoring Plugins Development Team 6* Copyright (c) 2005-2008 Monitoring Plugins Development Team
7* Original Author : Andreas Ericsson <ae@op5.se> 7* Original Author : Andreas Ericsson <ae@op5.se>
8* 8*
9* Description: 9* Description:
10* 10*
11* This file contains the check_icmp plugin 11* This file contains the check_icmp plugin
12* 12*
13* Relevant RFC's: 792 (ICMP), 791 (IP) 13* Relevant RFC's: 792 (ICMP), 791 (IP)
14* 14*
15* This program was modeled somewhat after the check_icmp program, 15* This program was modeled somewhat after the check_icmp program,
16* which was in turn a hack of fping (www.fping.org) but has been 16* which was in turn a hack of fping (www.fping.org) but has been
17* completely rewritten since to generate higher precision rta values, 17* completely rewritten since to generate higher precision rta values,
18* and support several different modes as well as setting ttl to control. 18* and support several different modes as well as setting ttl to control.
19* redundant routes. The only remainders of fping is currently a few 19* redundant routes. The only remainders of fping is currently a few
20* function names. 20* function names.
21* 21*
22* 22*
23* This program is free software: you can redistribute it and/or modify 23* This program is free software: you can redistribute it and/or modify
24* it under the terms of the GNU General Public License as published by 24* it under the terms of the GNU General Public License as published by
25* the Free Software Foundation, either version 3 of the License, or 25* the Free Software Foundation, either version 3 of the License, or
26* (at your option) any later version. 26* (at your option) any later version.
27* 27*
28* This program is distributed in the hope that it will be useful, 28* This program is distributed in the hope that it will be useful,
29* but WITHOUT ANY WARRANTY; without even the implied warranty of 29* but WITHOUT ANY WARRANTY; without even the implied warranty of
30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31* GNU General Public License for more details. 31* GNU General Public License for more details.
32* 32*
33* You should have received a copy of the GNU General Public License 33* You should have received a copy of the GNU General Public License
34* along with this program. If not, see <http://www.gnu.org/licenses/>. 34* along with this program. If not, see <http://www.gnu.org/licenses/>.
35* 35*
36* 36*
37*****************************************************************************/ 37*****************************************************************************/
38 38
39/* progname may change */ 39/* progname may change */
@@ -50,27 +50,20 @@ const char *email = "devel@monitoring-plugins.org";
50#if HAVE_SYS_SOCKIO_H 50#if HAVE_SYS_SOCKIO_H
51#include <sys/sockio.h> 51#include <sys/sockio.h>
52#endif 52#endif
53#include <sys/ioctl.h> 53
54#include <sys/time.h> 54#include <sys/time.h>
55#include <sys/types.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <stdarg.h>
59#include <unistd.h>
60#include <stddef.h>
61#include <errno.h> 55#include <errno.h>
62#include <string.h> 56#include <signal.h>
63#include <ctype.h> 57#include <ctype.h>
64#include <netdb.h> 58#include <float.h>
65#include <sys/socket.h>
66#include <net/if.h> 59#include <net/if.h>
67#include <netinet/in_systm.h> 60#include <netinet/in_systm.h>
68#include <netinet/in.h> 61#include <netinet/in.h>
69#include <netinet/ip.h> 62#include <netinet/ip.h>
63#include <netinet/ip6.h>
70#include <netinet/ip_icmp.h> 64#include <netinet/ip_icmp.h>
65#include <netinet/icmp6.h>
71#include <arpa/inet.h> 66#include <arpa/inet.h>
72#include <signal.h>
73#include <float.h>
74 67
75 68
76/** sometimes undefined system macros (quite a few, actually) **/ 69/** sometimes undefined system macros (quite a few, actually) **/
@@ -103,18 +96,14 @@ const char *email = "devel@monitoring-plugins.org";
103# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 96# define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
104#endif 97#endif
105 98
106#ifndef DBL_MAX
107# define DBL_MAX 9.9999999999e999
108#endif
109
110typedef unsigned short range_t; /* type for get_range() -- unimplemented */ 99typedef unsigned short range_t; /* type for get_range() -- unimplemented */
111 100
112typedef struct rta_host { 101typedef struct rta_host {
113 unsigned short id; /* id in **table, and icmp pkts */ 102 unsigned short id; /* id in **table, and icmp pkts */
114 char *name; /* arg used for adding this host */ 103 char *name; /* arg used for adding this host */
115 char *msg; /* icmp error message, if any */ 104 char *msg; /* icmp error message, if any */
116 struct sockaddr_in saddr_in; /* the address of this host */ 105 struct sockaddr_storage saddr_in; /* the address of this host */
117 struct in_addr error_addr; /* stores address of error replies */ 106 struct sockaddr_storage error_addr; /* stores address of error replies */
118 unsigned long long time_waited; /* total time waited, in usecs */ 107 unsigned long long time_waited; /* total time waited, in usecs */
119 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */ 108 unsigned int icmp_sent, icmp_recv, icmp_lost; /* counters */
120 unsigned char icmp_type, icmp_code; /* type and code from errors */ 109 unsigned char icmp_type, icmp_code; /* type and code from errors */
@@ -140,6 +129,18 @@ typedef struct icmp_ping_data {
140 unsigned short ping_id; 129 unsigned short ping_id;
141} icmp_ping_data; 130} icmp_ping_data;
142 131
132typedef union ip_hdr {
133 struct ip ip;
134 struct ip6_hdr ip6;
135} ip_hdr;
136
137typedef union icmp_packet {
138 void *buf;
139 struct icmp *icp;
140 struct icmp6_hdr *icp6;
141 u_short *cksum_in;
142} icmp_packet;
143
143/* the different modes of this program are as follows: 144/* the different modes of this program are as follows:
144 * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping) 145 * MODE_RTA: send all packets no matter what (mimic check_icmp and check_ping)
145 * MODE_HOSTCHECK: Return immediately upon any sign of life 146 * MODE_HOSTCHECK: Return immediately upon any sign of life
@@ -190,9 +191,10 @@ static int get_threshold(char *str, threshold *th);
190static void run_checks(void); 191static void run_checks(void);
191static void set_source_ip(char *); 192static void set_source_ip(char *);
192static int add_target(char *); 193static int add_target(char *);
193static int add_target_ip(char *, struct in_addr *); 194static int add_target_ip(char *, struct sockaddr_storage *);
194static int handle_random_icmp(unsigned char *, struct sockaddr_in *); 195static int handle_random_icmp(unsigned char *, struct sockaddr_storage *);
195static unsigned short icmp_checksum(unsigned short *, int); 196static void parse_address(struct sockaddr_storage *, char *, int);
197static unsigned short icmp_checksum(uint16_t *, size_t);
196static void finish(int); 198static void finish(int);
197static void crash(const char *, ...); 199static void crash(const char *, ...);
198 200
@@ -208,7 +210,7 @@ static int mode, protocols, sockets, debug = 0, timeout = 10;
208static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE; 210static unsigned short icmp_data_size = DEFAULT_PING_DATA_SIZE;
209static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN; 211static unsigned short icmp_pkt_size = DEFAULT_PING_DATA_SIZE + ICMP_MINLEN;
210 212
211static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0; 213static unsigned int icmp_sent = 0, icmp_recv = 0, icmp_lost = 0, ttl = 0;
212#define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost)) 214#define icmp_pkts_en_route (icmp_sent - (icmp_recv + icmp_lost))
213static unsigned short targets_down = 0, targets = 0, packets = 0; 215static unsigned short targets_down = 0, targets = 0, packets = 0;
214#define targets_alive (targets - targets_down) 216#define targets_alive (targets - targets_down)
@@ -218,7 +220,6 @@ static pid_t pid;
218static struct timezone tz; 220static struct timezone tz;
219static struct timeval prog_start; 221static struct timeval prog_start;
220static unsigned long long max_completion_time = 0; 222static unsigned long long max_completion_time = 0;
221static unsigned char ttl = 0; /* outgoing ttl */
222static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */ 223static unsigned int warn_down = 1, crit_down = 1; /* host down threshold values */
223static int min_hosts_alive = -1; 224static int min_hosts_alive = -1;
224float pkt_backoff_factor = 1.5; 225float pkt_backoff_factor = 1.5;
@@ -273,7 +274,7 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
273 break; 274 break;
274 275
275 case ICMP_TIMXCEED: 276 case ICMP_TIMXCEED:
276 /* really 'out of reach', or non-existant host behind a router serving 277 /* really 'out of reach', or non-existent host behind a router serving
277 * two different subnets */ 278 * two different subnets */
278 switch(icmp_code) { 279 switch(icmp_code) {
279 case ICMP_TIMXCEED_INTRANS: msg = "Time to live exceeded in transit"; break; 280 case ICMP_TIMXCEED_INTRANS: msg = "Time to live exceeded in transit"; break;
@@ -300,7 +301,7 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
300} 301}
301 302
302static int 303static int
303handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr) 304handle_random_icmp(unsigned char *packet, struct sockaddr_storage *addr)
304{ 305{
305 struct icmp p, sent_icmp; 306 struct icmp p, sent_icmp;
306 struct rta_host *host = NULL; 307 struct rta_host *host = NULL;
@@ -342,9 +343,11 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr)
342 /* it is indeed a response for us */ 343 /* it is indeed a response for us */
343 host = table[ntohs(sent_icmp.icmp_seq)/packets]; 344 host = table[ntohs(sent_icmp.icmp_seq)/packets];
344 if(debug) { 345 if(debug) {
346 char address[INET6_ADDRSTRLEN];
347 parse_address(addr, address, sizeof(address));
345 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n", 348 printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n",
346 get_icmp_error_msg(p.icmp_type, p.icmp_code), 349 get_icmp_error_msg(p.icmp_type, p.icmp_code),
347 inet_ntoa(addr->sin_addr), host->name); 350 address, host->name);
348 } 351 }
349 352
350 icmp_lost++; 353 icmp_lost++;
@@ -364,11 +367,23 @@ handle_random_icmp(unsigned char *packet, struct sockaddr_in *addr)
364 } 367 }
365 host->icmp_type = p.icmp_type; 368 host->icmp_type = p.icmp_type;
366 host->icmp_code = p.icmp_code; 369 host->icmp_code = p.icmp_code;
367 host->error_addr.s_addr = addr->sin_addr.s_addr; 370 host->error_addr = *addr;
368 371
369 return 0; 372 return 0;
370} 373}
371 374
375void parse_address(struct sockaddr_storage *addr, char *address, int size)
376{
377 switch (address_family) {
378 case AF_INET:
379 inet_ntop(address_family, &((struct sockaddr_in *)addr)->sin_addr, address, size);
380 break;
381 case AF_INET6:
382 inet_ntop(address_family, &((struct sockaddr_in6 *)addr)->sin6_addr, address, size);
383 break;
384 }
385}
386
372int 387int
373main(int argc, char **argv) 388main(int argc, char **argv)
374{ 389{
@@ -381,6 +396,8 @@ main(int argc, char **argv)
381#ifdef SO_TIMESTAMP 396#ifdef SO_TIMESTAMP
382 int on = 1; 397 int on = 1;
383#endif 398#endif
399 char *source_ip = NULL;
400 char * opts_str = "vhVw:c:n:p:t:H:s:i:b:I:l:m:64";
384 401
385 setlocale (LC_ALL, ""); 402 setlocale (LC_ALL, "");
386 bindtextdomain (PACKAGE, LOCALEDIR); 403 bindtextdomain (PACKAGE, LOCALEDIR);
@@ -390,33 +407,8 @@ main(int argc, char **argv)
390 * that before pointer magic (esp. on network data) */ 407 * that before pointer magic (esp. on network data) */
391 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0; 408 icmp_sockerrno = udp_sockerrno = tcp_sockerrno = sockets = 0;
392 409
393 if((icmp_sock = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1) 410 address_family = -1;
394 sockets |= HAVE_ICMP; 411 int icmp_proto = IPPROTO_ICMP;
395 else icmp_sockerrno = errno;
396
397 /* if((udp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1) */
398 /* sockets |= HAVE_UDP; */
399 /* else udp_sockerrno = errno; */
400
401 /* if((tcp_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) */
402 /* sockets |= HAVE_TCP; */
403 /* else tcp_sockerrno = errno; */
404
405 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */
406 setuid(getuid());
407
408#ifdef SO_TIMESTAMP
409 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
410 if(debug) printf("Warning: no SO_TIMESTAMP support\n");
411#endif // SO_TIMESTAMP
412
413 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */
414 environ = NULL;
415
416 /* use the pid to mark packets as ours */
417 /* Some systems have 32-bit pid_t so mask off only 16 bits */
418 pid = getpid() & 0xffff;
419 /* printf("pid = %u\n", pid); */
420 412
421 /* get calling name the old-fashioned way for portability instead 413 /* get calling name the old-fashioned way for portability instead
422 * of relying on the glibc-ism __progname */ 414 * of relying on the glibc-ism __progname */
@@ -456,9 +448,6 @@ main(int argc, char **argv)
456 packets = 5; 448 packets = 5;
457 } 449 }
458 450
459 /* Parse extra opts if any */
460 argv=np_extra_opts(&argc, argv, progname);
461
462 /* support "--help" and "--version" */ 451 /* support "--help" and "--version" */
463 if(argc == 2) { 452 if(argc == 2) {
464 if(!strcmp(argv[1], "--help")) 453 if(!strcmp(argv[1], "--help"))
@@ -467,10 +456,35 @@ main(int argc, char **argv)
467 strcpy(argv[1], "-V"); 456 strcpy(argv[1], "-V");
468 } 457 }
469 458
459 /* Parse protocol arguments first */
460 for(i = 1; i < argc; i++) {
461 while((arg = getopt(argc, argv, opts_str)) != EOF) {
462 switch(arg) {
463 case '4':
464 if (address_family != -1)
465 crash("Multiple protocol versions not supported");
466 address_family = AF_INET;
467 break;
468 case '6':
469#ifdef USE_IPV6
470 if (address_family != -1)
471 crash("Multiple protocol versions not supported");
472 address_family = AF_INET6;
473#else
474 usage (_("IPv6 support not available\n"));
475#endif
476 break;
477 }
478 }
479 }
480
481 /* Reset argument scanning */
482 optind = 1;
483
484 unsigned short size;
470 /* parse the arguments */ 485 /* parse the arguments */
471 for(i = 1; i < argc; i++) { 486 for(i = 1; i < argc; i++) {
472 while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) { 487 while((arg = getopt(argc, argv, opts_str)) != EOF) {
473 unsigned short size;
474 switch(arg) { 488 switch(arg) {
475 case 'v': 489 case 'v':
476 debug++; 490 debug++;
@@ -482,7 +496,7 @@ main(int argc, char **argv)
482 icmp_data_size = size; 496 icmp_data_size = size;
483 icmp_pkt_size = size + ICMP_MINLEN; 497 icmp_pkt_size = size + ICMP_MINLEN;
484 } else 498 } else
485 usage_va("ICMP data length must be between: %d and %d", 499 usage_va("ICMP data length must be between: %lu and %lu",
486 sizeof(struct icmp) + sizeof(struct icmp_ping_data), 500 sizeof(struct icmp) + sizeof(struct icmp_ping_data),
487 MAX_PING_DATA - 1); 501 MAX_PING_DATA - 1);
488 break; 502 break;
@@ -510,7 +524,7 @@ main(int argc, char **argv)
510 add_target(optarg); 524 add_target(optarg);
511 break; 525 break;
512 case 'l': 526 case 'l':
513 ttl = (unsigned char)strtoul(optarg, NULL, 0); 527 ttl = (int)strtoul(optarg, NULL, 0);
514 break; 528 break;
515 case 'm': 529 case 'm':
516 min_hosts_alive = (int)strtoul(optarg, NULL, 0); 530 min_hosts_alive = (int)strtoul(optarg, NULL, 0);
@@ -522,7 +536,7 @@ main(int argc, char **argv)
522 } 536 }
523 break; 537 break;
524 case 's': /* specify source IP address */ 538 case 's': /* specify source IP address */
525 set_source_ip(optarg); 539 source_ip = optarg;
526 break; 540 break;
527 case 'V': /* version */ 541 case 'V': /* version */
528 print_revision (progname, NP_VERSION); 542 print_revision (progname, NP_VERSION);
@@ -530,10 +544,22 @@ main(int argc, char **argv)
530 case 'h': /* help */ 544 case 'h': /* help */
531 print_help (); 545 print_help ();
532 exit (STATE_UNKNOWN); 546 exit (STATE_UNKNOWN);
547 break;
533 } 548 }
534 } 549 }
535 } 550 }
536 551
552 /* POSIXLY_CORRECT might break things, so unset it (the portable way) */
553 environ = NULL;
554
555 /* use the pid to mark packets as ours */
556 /* Some systems have 32-bit pid_t so mask off only 16 bits */
557 pid = getpid() & 0xffff;
558 /* printf("pid = %u\n", pid); */
559
560 /* Parse extra opts if any */
561 argv=np_extra_opts(&argc, argv, progname);
562
537 argv = &argv[optind]; 563 argv = &argv[optind];
538 while(*argv) { 564 while(*argv) {
539 add_target(*argv); 565 add_target(*argv);
@@ -545,6 +571,32 @@ main(int argc, char **argv)
545 exit(3); 571 exit(3);
546 } 572 }
547 573
574 // add_target might change address_family
575 switch ( address_family ){
576 case AF_INET: icmp_proto = IPPROTO_ICMP;
577 break;
578 case AF_INET6: icmp_proto = IPPROTO_ICMPV6;
579 break;
580 default: crash("Address family not supported");
581 }
582 if((icmp_sock = socket(address_family, SOCK_RAW, icmp_proto)) != -1)
583 sockets |= HAVE_ICMP;
584 else icmp_sockerrno = errno;
585
586 if( source_ip )
587 set_source_ip(source_ip);
588
589#ifdef SO_TIMESTAMP
590 if(setsockopt(icmp_sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)))
591 if(debug) printf("Warning: no SO_TIMESTAMP support\n");
592#endif // SO_TIMESTAMP
593
594 /* now drop privileges (no effect if not setsuid or geteuid() == 0) */
595 if (setuid(getuid()) == -1) {
596 printf("ERROR: Failed to drop privileges\n");
597 return 1;
598 }
599
548 if(!sockets) { 600 if(!sockets) {
549 if(icmp_sock == -1) { 601 if(icmp_sock == -1) {
550 errno = icmp_sockerrno; 602 errno = icmp_sockerrno;
@@ -608,7 +660,7 @@ main(int argc, char **argv)
608 if(max_completion_time > (u_int)timeout * 1000000) { 660 if(max_completion_time > (u_int)timeout * 1000000) {
609 printf("max_completion_time: %llu timeout: %u\n", 661 printf("max_completion_time: %llu timeout: %u\n",
610 max_completion_time, timeout); 662 max_completion_time, timeout);
611 printf("Timout must be at lest %llu\n", 663 printf("Timeout must be at least %llu\n",
612 max_completion_time / 1000000 + 1); 664 max_completion_time / 1000000 + 1);
613 } 665 }
614 } 666 }
@@ -633,7 +685,7 @@ main(int argc, char **argv)
633 } 685 }
634 686
635 host = list; 687 host = list;
636 table = malloc(sizeof(struct rta_host **) * targets); 688 table = (struct rta_host**)malloc(sizeof(struct rta_host **) * targets);
637 i = 0; 689 i = 0;
638 while(host) { 690 while(host) {
639 host->id = i*packets; 691 host->id = i*packets;
@@ -653,7 +705,7 @@ main(int argc, char **argv)
653static void 705static void
654run_checks() 706run_checks()
655{ 707{
656 u_int i, t, result; 708 u_int i, t;
657 u_int final_wait, time_passed; 709 u_int final_wait, time_passed;
658 710
659 /* this loop might actually violate the pkt_interval or target_interval 711 /* this loop might actually violate the pkt_interval or target_interval
@@ -671,9 +723,9 @@ run_checks()
671 723
672 /* we're still in the game, so send next packet */ 724 /* we're still in the game, so send next packet */
673 (void)send_icmp_ping(icmp_sock, table[t]); 725 (void)send_icmp_ping(icmp_sock, table[t]);
674 result = wait_for_reply(icmp_sock, target_interval); 726 wait_for_reply(icmp_sock, target_interval);
675 } 727 }
676 result = wait_for_reply(icmp_sock, pkt_interval * targets); 728 wait_for_reply(icmp_sock, pkt_interval * targets);
677 } 729 }
678 730
679 if(icmp_pkts_en_route && targets_alive) { 731 if(icmp_pkts_en_route && targets_alive) {
@@ -693,30 +745,47 @@ run_checks()
693 * haven't yet */ 745 * haven't yet */
694 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n", 746 if(debug) printf("Waiting for %u micro-seconds (%0.3f msecs)\n",
695 final_wait, (float)final_wait / 1000); 747 final_wait, (float)final_wait / 1000);
696 result = wait_for_reply(icmp_sock, final_wait); 748 wait_for_reply(icmp_sock, final_wait);
697 } 749 }
698} 750}
699 751
752
700/* response structure: 753/* response structure:
754 * IPv4:
701 * ip header : 20 bytes 755 * ip header : 20 bytes
702 * icmp header : 28 bytes 756 * icmp header : 28 bytes
757 * IPv6:
758 * ip header : 40 bytes
759 * icmp header : 28 bytes
760 * both:
703 * icmp echo reply : the rest 761 * icmp echo reply : the rest
704 */ 762 */
705static int 763static int
706wait_for_reply(int sock, u_int t) 764wait_for_reply(int sock, u_int t)
707{ 765{
708 int n, hlen; 766 int n, hlen;
709 static unsigned char buf[4096]; 767 static unsigned char buf[65536];
710 struct sockaddr_in resp_addr; 768 struct sockaddr_storage resp_addr;
711 struct ip *ip; 769 union ip_hdr *ip;
712 struct icmp icp; 770 union icmp_packet packet;
713 struct rta_host *host; 771 struct rta_host *host;
714 struct icmp_ping_data data; 772 struct icmp_ping_data data;
715 struct timeval wait_start, now; 773 struct timeval wait_start, now;
716 u_int tdiff, i, per_pkt_wait; 774 u_int tdiff, i, per_pkt_wait;
717 775
776 if (!(packet.buf = malloc(icmp_pkt_size))) {
777 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
778 icmp_pkt_size);
779 return -1; /* might be reached if we're in debug mode */
780 }
781
782 memset(packet.buf, 0, icmp_pkt_size);
783
718 /* if we can't listen or don't have anything to listen to, just return */ 784 /* if we can't listen or don't have anything to listen to, just return */
719 if(!t || !icmp_pkts_en_route) return 0; 785 if(!t || !icmp_pkts_en_route) {
786 free(packet.buf);
787 return 0;
788 }
720 789
721 gettimeofday(&wait_start, &tz); 790 gettimeofday(&wait_start, &tz);
722 791
@@ -735,7 +804,7 @@ wait_for_reply(int sock, u_int t)
735 804
736 /* reap responses until we hit a timeout */ 805 /* reap responses until we hit a timeout */
737 n = recvfrom_wto(sock, buf, sizeof(buf), 806 n = recvfrom_wto(sock, buf, sizeof(buf),
738 (struct sockaddr *)&resp_addr, &t, &now); 807 (struct sockaddr *)&resp_addr, &t, &now);
739 if(!n) { 808 if(!n) {
740 if(debug > 1) { 809 if(debug > 1) {
741 printf("recvfrom_wto() timed out during a %u usecs wait\n", 810 printf("recvfrom_wto() timed out during a %u usecs wait\n",
@@ -745,12 +814,23 @@ wait_for_reply(int sock, u_int t)
745 } 814 }
746 if(n < 0) { 815 if(n < 0) {
747 if(debug) printf("recvfrom_wto() returned errors\n"); 816 if(debug) printf("recvfrom_wto() returned errors\n");
817 free(packet.buf);
748 return n; 818 return n;
749 } 819 }
750 820
751 ip = (struct ip *)buf; 821 // FIXME: with ipv6 we don't have an ip header here
752 if(debug > 1) printf("received %u bytes from %s\n", 822 if (address_family != AF_INET6) {
753 ntohs(ip->ip_len), inet_ntoa(resp_addr.sin_addr)); 823 ip = (union ip_hdr *)buf;
824
825 if(debug > 1) {
826 char address[INET6_ADDRSTRLEN];
827 parse_address(&resp_addr, address, sizeof(address));
828 printf("received %u bytes from %s\n",
829 address_family == AF_INET6 ? ntohs(ip->ip6.ip6_plen)
830 : ntohs(ip->ip.ip_len),
831 address);
832 }
833 }
754 834
755/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */ 835/* obsolete. alpha on tru64 provides the necessary defines, but isn't broken */
756/* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */ 836/* #if defined( __alpha__ ) && __STDC__ && !defined( __GLIBC__ ) */
@@ -759,12 +839,14 @@ wait_for_reply(int sock, u_int t)
759 * off the bottom 4 bits */ 839 * off the bottom 4 bits */
760/* hlen = (ip->ip_vhl & 0x0f) << 2; */ 840/* hlen = (ip->ip_vhl & 0x0f) << 2; */
761/* #else */ 841/* #else */
762 hlen = ip->ip_hl << 2; 842 hlen = (address_family == AF_INET6) ? 0 : ip->ip.ip_hl << 2;
763/* #endif */ 843/* #endif */
764 844
765 if(n < (hlen + ICMP_MINLEN)) { 845 if(n < (hlen + ICMP_MINLEN)) {
846 char address[INET6_ADDRSTRLEN];
847 parse_address(&resp_addr, address, sizeof(address));
766 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n", 848 crash("received packet too short for ICMP (%d bytes, expected %d) from %s\n",
767 n, hlen + icmp_pkt_size, inet_ntoa(resp_addr.sin_addr)); 849 n, hlen + icmp_pkt_size, address);
768 } 850 }
769 /* else if(debug) { */ 851 /* else if(debug) { */
770 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */ 852 /* printf("ip header size: %u, packet size: %u (expected %u, %u)\n", */
@@ -773,23 +855,39 @@ wait_for_reply(int sock, u_int t)
773 /* } */ 855 /* } */
774 856
775 /* check the response */ 857 /* check the response */
776 memcpy(&icp, buf + hlen, sizeof(icp));
777 858
778 if(ntohs(icp.icmp_id) != pid || icp.icmp_type != ICMP_ECHOREPLY || 859 memcpy(packet.buf, buf + hlen, icmp_pkt_size);
779 ntohs(icp.icmp_seq) >= targets*packets) { 860/* address_family == AF_INET6 ? sizeof(struct icmp6_hdr)
861 : sizeof(struct icmp));*/
862
863 if( (address_family == PF_INET &&
864 (ntohs(packet.icp->icmp_id) != pid || packet.icp->icmp_type != ICMP_ECHOREPLY
865 || ntohs(packet.icp->icmp_seq) >= targets * packets))
866 || (address_family == PF_INET6 &&
867 (ntohs(packet.icp6->icmp6_id) != pid || packet.icp6->icmp6_type != ICMP6_ECHO_REPLY
868 || ntohs(packet.icp6->icmp6_seq) >= targets * packets))) {
780 if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n"); 869 if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n");
781 handle_random_icmp(buf + hlen, &resp_addr); 870 handle_random_icmp(buf + hlen, &resp_addr);
782 continue; 871 continue;
783 } 872 }
784 873
785 /* this is indeed a valid response */ 874 /* this is indeed a valid response */
786 memcpy(&data, icp.icmp_data, sizeof(data)); 875 if (address_family == PF_INET) {
787 if (debug > 2) 876 memcpy(&data, packet.icp->icmp_data, sizeof(data));
788 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n", 877 if (debug > 2)
789 (unsigned long)sizeof(data), ntohs(icp.icmp_id), 878 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n",
790 ntohs(icp.icmp_seq), icp.icmp_cksum); 879 (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id),
880 ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum);
881 host = table[ntohs(packet.icp->icmp_seq)/packets];
882 } else {
883 memcpy(&data, &packet.icp6->icmp6_dataun.icmp6_un_data8[4], sizeof(data));
884 if (debug > 2)
885 printf("ICMP echo-reply of len %lu, id %u, seq %u, cksum 0x%X\n",
886 (unsigned long)sizeof(data), ntohs(packet.icp6->icmp6_id),
887 ntohs(packet.icp6->icmp6_seq), packet.icp6->icmp6_cksum);
888 host = table[ntohs(packet.icp6->icmp6_seq)/packets];
889 }
791 890
792 host = table[ntohs(icp.icmp_seq)/packets];
793 tdiff = get_timevaldiff(&data.stime, &now); 891 tdiff = get_timevaldiff(&data.stime, &now);
794 892
795 host->time_waited += tdiff; 893 host->time_waited += tdiff;
@@ -801,22 +899,43 @@ wait_for_reply(int sock, u_int t)
801 host->rtmin = tdiff; 899 host->rtmin = tdiff;
802 900
803 if(debug) { 901 if(debug) {
804 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n", 902 char address[INET6_ADDRSTRLEN];
805 (float)tdiff / 1000, inet_ntoa(resp_addr.sin_addr), 903 parse_address(&resp_addr, address, sizeof(address));
806 ttl, ip->ip_ttl, (float)host->rtmax / 1000, (float)host->rtmin / 1000); 904
905 switch(address_family) {
906 case AF_INET: {
907 printf("%0.3f ms rtt from %s, outgoing ttl: %u, incoming ttl: %u, max: %0.3f, min: %0.3f\n",
908 (float)tdiff / 1000,
909 address,
910 ttl,
911 ip->ip.ip_ttl,
912 (float)host->rtmax / 1000,
913 (float)host->rtmin / 1000);
914 break;
915 };
916 case AF_INET6: {
917 printf("%0.3f ms rtt from %s, outgoing ttl: %u, max: %0.3f, min: %0.3f\n",
918 (float)tdiff / 1000,
919 address,
920 ttl,
921 (float)host->rtmax / 1000,
922 (float)host->rtmin / 1000);
923 };
924 }
807 } 925 }
808 926
809 /* if we're in hostcheck mode, exit with limited printouts */ 927 /* if we're in hostcheck mode, exit with limited printouts */
810 if(mode == MODE_HOSTCHECK) { 928 if(mode == MODE_HOSTCHECK) {
811 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|" 929 printf("OK - %s responds to ICMP. Packet %u, rta %0.3fms|"
812 "pkt=%u;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n", 930 "pkt=%u;;;0;%u rta=%0.3f;%0.3f;%0.3f;;\n",
813 host->name, icmp_recv, (float)tdiff / 1000, 931 host->name, icmp_recv, (float)tdiff / 1000,
814 icmp_recv, packets, (float)tdiff / 1000, 932 icmp_recv, packets, (float)tdiff / 1000,
815 (float)warn.rta / 1000, (float)crit.rta / 1000); 933 (float)warn.rta / 1000, (float)crit.rta / 1000);
816 exit(STATE_OK); 934 exit(STATE_OK);
817 } 935 }
818 } 936 }
819 937
938 free(packet.buf);
820 return 0; 939 return 0;
821} 940}
822 941
@@ -824,62 +943,86 @@ wait_for_reply(int sock, u_int t)
824static int 943static int
825send_icmp_ping(int sock, struct rta_host *host) 944send_icmp_ping(int sock, struct rta_host *host)
826{ 945{
827 static union {
828 void *buf; /* re-use so we prevent leaks */
829 struct icmp *icp;
830 u_short *cksum_in;
831 } packet = { NULL };
832 long int len; 946 long int len;
947 size_t addrlen;
833 struct icmp_ping_data data; 948 struct icmp_ping_data data;
834 struct msghdr hdr; 949 struct msghdr hdr;
835 struct iovec iov; 950 struct iovec iov;
836 struct timeval tv; 951 struct timeval tv;
837 struct sockaddr *addr; 952 void *buf = NULL;
838 953
839 if(sock == -1) { 954 if(sock == -1) {
840 errno = 0; 955 errno = 0;
841 crash("Attempt to send on bogus socket"); 956 crash("Attempt to send on bogus socket");
842 return -1; 957 return -1;
843 } 958 }
844 addr = (struct sockaddr *)&host->saddr_in;
845 959
846 if(!packet.buf) { 960 if(!buf) {
847 if (!(packet.buf = malloc(icmp_pkt_size))) { 961 if (!(buf = malloc(icmp_pkt_size))) {
848 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer", 962 crash("send_icmp_ping(): failed to malloc %d bytes for send buffer",
849 icmp_pkt_size); 963 icmp_pkt_size);
850 return -1; /* might be reached if we're in debug mode */ 964 return -1; /* might be reached if we're in debug mode */
851 } 965 }
852 } 966 }
853 memset(packet.buf, 0, icmp_pkt_size); 967 memset(buf, 0, icmp_pkt_size);
854 968
855 if((gettimeofday(&tv, &tz)) == -1) return -1; 969 if((gettimeofday(&tv, &tz)) == -1) {
970 free(buf);
971 return -1;
972 }
856 973
857 data.ping_id = 10; /* host->icmp.icmp_sent; */ 974 data.ping_id = 10; /* host->icmp.icmp_sent; */
858 memcpy(&data.stime, &tv, sizeof(tv)); 975 memcpy(&data.stime, &tv, sizeof(tv));
859 memcpy(&packet.icp->icmp_data, &data, sizeof(data)); 976
860 packet.icp->icmp_type = ICMP_ECHO; 977 if (address_family == AF_INET) {
861 packet.icp->icmp_code = 0; 978 struct icmp *icp = (struct icmp*)buf;
862 packet.icp->icmp_cksum = 0; 979 addrlen = sizeof(struct sockaddr_in);
863 packet.icp->icmp_id = htons(pid); 980
864 packet.icp->icmp_seq = htons(host->id++); 981 memcpy(&icp->icmp_data, &data, sizeof(data));
865 packet.icp->icmp_cksum = icmp_checksum(packet.cksum_in, icmp_pkt_size); 982
866 983 icp->icmp_type = ICMP_ECHO;
867 if (debug > 2) 984 icp->icmp_code = 0;
868 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n", 985 icp->icmp_cksum = 0;
869 (unsigned long)sizeof(data), ntohs(packet.icp->icmp_id), 986 icp->icmp_id = htons(pid);
870 ntohs(packet.icp->icmp_seq), packet.icp->icmp_cksum, 987 icp->icmp_seq = htons(host->id++);
871 host->name); 988 icp->icmp_cksum = icmp_checksum((uint16_t*)buf, (size_t)icmp_pkt_size);
989
990 if (debug > 2)
991 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
992 (unsigned long)sizeof(data), ntohs(icp->icmp_id), ntohs(icp->icmp_seq), icp->icmp_cksum, host->name);
993 }
994 else {
995 struct icmp6_hdr *icp6 = (struct icmp6_hdr*)buf;
996 addrlen = sizeof(struct sockaddr_in6);
997
998 memcpy(&icp6->icmp6_dataun.icmp6_un_data8[4], &data, sizeof(data));
999
1000 icp6->icmp6_type = ICMP6_ECHO_REQUEST;
1001 icp6->icmp6_code = 0;
1002 icp6->icmp6_cksum = 0;
1003 icp6->icmp6_id = htons(pid);
1004 icp6->icmp6_seq = htons(host->id++);
1005 // let checksum be calculated automatically
1006
1007 if (debug > 2) {
1008 printf("Sending ICMP echo-request of len %lu, id %u, seq %u, cksum 0x%X to host %s\n",
1009 (unsigned long)sizeof(data), ntohs(icp6->icmp6_id),
1010 ntohs(icp6->icmp6_seq), icp6->icmp6_cksum, host->name);
1011 }
1012 }
872 1013
873 memset(&iov, 0, sizeof(iov)); 1014 memset(&iov, 0, sizeof(iov));
874 iov.iov_base = packet.buf; 1015 iov.iov_base = buf;
875 iov.iov_len = icmp_pkt_size; 1016 iov.iov_len = icmp_pkt_size;
876 1017
877 memset(&hdr, 0, sizeof(hdr)); 1018 memset(&hdr, 0, sizeof(hdr));
878 hdr.msg_name = addr; 1019 hdr.msg_name = (struct sockaddr *)&host->saddr_in;
879 hdr.msg_namelen = sizeof(struct sockaddr); 1020 hdr.msg_namelen = addrlen;
880 hdr.msg_iov = &iov; 1021 hdr.msg_iov = &iov;
881 hdr.msg_iovlen = 1; 1022 hdr.msg_iovlen = 1;
882 1023
1024 errno = 0;
1025
883/* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */ 1026/* MSG_CONFIRM is a linux thing and only available on linux kernels >= 2.3.15, see send(2) */
884#ifdef MSG_CONFIRM 1027#ifdef MSG_CONFIRM
885 len = sendmsg(sock, &hdr, MSG_CONFIRM); 1028 len = sendmsg(sock, &hdr, MSG_CONFIRM);
@@ -887,9 +1030,15 @@ send_icmp_ping(int sock, struct rta_host *host)
887 len = sendmsg(sock, &hdr, 0); 1030 len = sendmsg(sock, &hdr, 0);
888#endif 1031#endif
889 1032
1033 free(buf);
1034
890 if(len < 0 || (unsigned int)len != icmp_pkt_size) { 1035 if(len < 0 || (unsigned int)len != icmp_pkt_size) {
891 if(debug) printf("Failed to send ping to %s\n", 1036 if(debug) {
892 inet_ntoa(host->saddr_in.sin_addr)); 1037 char address[INET6_ADDRSTRLEN];
1038 parse_address((struct sockaddr_storage *)&host->saddr_in, address, sizeof(address));
1039 printf("Failed to send ping to %s: %s\n", address, strerror(errno));
1040 }
1041 errno = 0;
893 return -1; 1042 return -1;
894 } 1043 }
895 1044
@@ -934,7 +1083,7 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
934 1083
935 if(!n) return 0; /* timeout */ 1084 if(!n) return 0; /* timeout */
936 1085
937 slen = sizeof(struct sockaddr); 1086 slen = sizeof(struct sockaddr_storage);
938 1087
939 memset(&iov, 0, sizeof(iov)); 1088 memset(&iov, 0, sizeof(iov));
940 iov.iov_base = buf; 1089 iov.iov_base = buf;
@@ -958,6 +1107,7 @@ recvfrom_wto(int sock, void *buf, unsigned int len, struct sockaddr *saddr,
958 break ; 1107 break ;
959 } 1108 }
960 } 1109 }
1110
961 if (!chdr) 1111 if (!chdr)
962#endif // SO_TIMESTAMP 1112#endif // SO_TIMESTAMP
963 gettimeofday(tv, &tz); 1113 gettimeofday(tv, &tz);
@@ -991,10 +1141,11 @@ finish(int sig)
991 1141
992 /* iterate thrice to calculate values, give output, and print perfparse */ 1142 /* iterate thrice to calculate values, give output, and print perfparse */
993 host = list; 1143 host = list;
1144
994 while(host) { 1145 while(host) {
995 if(!host->icmp_recv) { 1146 if(!host->icmp_recv) {
996 /* rta 0 is ofcourse not entirely correct, but will still show up 1147 /* rta 0 is ofcourse not entirely correct, but will still show up
997 * conspicuosly as missing entries in perfparse and cacti */ 1148 * conspicuously as missing entries in perfparse and cacti */
998 pl = 100; 1149 pl = 100;
999 rta = 0; 1150 rta = 0;
1000 status = STATE_CRITICAL; 1151 status = STATE_CRITICAL;
@@ -1039,10 +1190,12 @@ finish(int sig)
1039 if(!host->icmp_recv) { 1190 if(!host->icmp_recv) {
1040 status = STATE_CRITICAL; 1191 status = STATE_CRITICAL;
1041 if(host->flags & FLAG_LOST_CAUSE) { 1192 if(host->flags & FLAG_LOST_CAUSE) {
1193 char address[INET6_ADDRSTRLEN];
1194 parse_address(&host->error_addr, address, sizeof(address));
1042 printf("%s: %s @ %s. rta nan, lost %d%%", 1195 printf("%s: %s @ %s. rta nan, lost %d%%",
1043 host->name, 1196 host->name,
1044 get_icmp_error_msg(host->icmp_type, host->icmp_code), 1197 get_icmp_error_msg(host->icmp_type, host->icmp_code),
1045 inet_ntoa(host->error_addr), 1198 address,
1046 100); 1199 100);
1047 } 1200 }
1048 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 */
@@ -1068,7 +1221,7 @@ finish(int sig)
1068 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000, 1221 host->rta / 1000, (float)warn.rta / 1000, (float)crit.rta / 1000,
1069 (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl, 1222 (targets > 1) ? host->name : "", host->pl, warn.pl, crit.pl,
1070 (targets > 1) ? host->name : "", (float)host->rtmax / 1000, 1223 (targets > 1) ? host->name : "", (float)host->rtmax / 1000,
1071 (targets > 1) ? host->name : "", (host->rtmin < DBL_MAX) ? (float)host->rtmin / 1000 : (float)0); 1224 (targets > 1) ? host->name : "", (host->rtmin < INFINITY) ? (float)host->rtmin / 1000 : (float)0);
1072 1225
1073 host = host->next; 1226 host = host->next;
1074 } 1227 }
@@ -1104,7 +1257,6 @@ get_timevaldiff(struct timeval *early, struct timeval *later)
1104 { 1257 {
1105 return 0; 1258 return 0;
1106 } 1259 }
1107
1108 ret = (later->tv_sec - early->tv_sec) * 1000000; 1260 ret = (later->tv_sec - early->tv_sec) * 1000000;
1109 ret += later->tv_usec - early->tv_usec; 1261 ret += later->tv_usec - early->tv_usec;
1110 1262
@@ -1112,18 +1264,35 @@ get_timevaldiff(struct timeval *early, struct timeval *later)
1112} 1264}
1113 1265
1114static int 1266static int
1115add_target_ip(char *arg, struct in_addr *in) 1267add_target_ip(char *arg, struct sockaddr_storage *in)
1116{ 1268{
1117 struct rta_host *host; 1269 struct rta_host *host;
1270 struct sockaddr_in *sin, *host_sin;
1271 struct sockaddr_in6 *sin6, *host_sin6;
1118 1272
1119 /* disregard obviously stupid addresses */ 1273 if (address_family == AF_INET)
1120 if(in->s_addr == INADDR_NONE || in->s_addr == INADDR_ANY) 1274 sin = (struct sockaddr_in *)in;
1275 else
1276 sin6 = (struct sockaddr_in6 *)in;
1277
1278
1279
1280 /* disregard obviously stupid addresses
1281 * (I didn't find an ipv6 equivalent to INADDR_NONE) */
1282 if (((address_family == AF_INET && (sin->sin_addr.s_addr == INADDR_NONE
1283 || sin->sin_addr.s_addr == INADDR_ANY)))
1284 || (address_family == AF_INET6 && (sin6->sin6_addr.s6_addr == in6addr_any.s6_addr))) {
1121 return -1; 1285 return -1;
1286 }
1122 1287
1123 /* no point in adding two identical IP's, so don't. ;) */ 1288 /* no point in adding two identical IP's, so don't. ;) */
1124 host = list; 1289 host = list;
1125 while(host) { 1290 while(host) {
1126 if(host->saddr_in.sin_addr.s_addr == in->s_addr) { 1291 host_sin = (struct sockaddr_in *)&host->saddr_in;
1292 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1293
1294 if( (address_family == AF_INET && host_sin->sin_addr.s_addr == sin->sin_addr.s_addr)
1295 || (address_family == AF_INET6 && host_sin6->sin6_addr.s6_addr == sin6->sin6_addr.s6_addr)) {
1127 if(debug) printf("Identical IP already exists. Not adding %s\n", arg); 1296 if(debug) printf("Identical IP already exists. Not adding %s\n", arg);
1128 return -1; 1297 return -1;
1129 } 1298 }
@@ -1131,21 +1300,31 @@ add_target_ip(char *arg, struct in_addr *in)
1131 } 1300 }
1132 1301
1133 /* add the fresh ip */ 1302 /* add the fresh ip */
1134 host = malloc(sizeof(struct rta_host)); 1303 host = (struct rta_host*)malloc(sizeof(struct rta_host));
1135 if(!host) { 1304 if(!host) {
1136 crash("add_target_ip(%s, %s): malloc(%d) failed", 1305 char straddr[INET6_ADDRSTRLEN];
1137 arg, inet_ntoa(*in), sizeof(struct rta_host)); 1306 parse_address((struct sockaddr_storage*)&in, straddr, sizeof(straddr));
1307 crash("add_target_ip(%s, %s): malloc(%lu) failed",
1308 arg, straddr, sizeof(struct rta_host));
1138 } 1309 }
1139 memset(host, 0, sizeof(struct rta_host)); 1310 memset(host, 0, sizeof(struct rta_host));
1140 1311
1141 /* set the values. use calling name for output */ 1312 /* set the values. use calling name for output */
1142 host->name = strdup(arg); 1313 host->name = strdup(arg);
1143 1314
1144 /* fill out the sockaddr_in struct */ 1315 /* fill out the sockaddr_storage struct */
1145 host->saddr_in.sin_family = AF_INET; 1316 if(address_family == AF_INET) {
1146 host->saddr_in.sin_addr.s_addr = in->s_addr; 1317 host_sin = (struct sockaddr_in *)&host->saddr_in;
1318 host_sin->sin_family = AF_INET;
1319 host_sin->sin_addr.s_addr = sin->sin_addr.s_addr;
1320 }
1321 else {
1322 host_sin6 = (struct sockaddr_in6 *)&host->saddr_in;
1323 host_sin6->sin6_family = AF_INET6;
1324 memcpy(host_sin6->sin6_addr.s6_addr, sin6->sin6_addr.s6_addr, sizeof host_sin6->sin6_addr.s6_addr);
1325 }
1147 1326
1148 host->rtmin = DBL_MAX; 1327 host->rtmin = INFINITY;
1149 1328
1150 if(!list) list = cursor = host; 1329 if(!list) list = cursor = host;
1151 else cursor->next = host; 1330 else cursor->next = host;
@@ -1160,31 +1339,67 @@ add_target_ip(char *arg, struct in_addr *in)
1160static int 1339static int
1161add_target(char *arg) 1340add_target(char *arg)
1162{ 1341{
1163 int i; 1342 int error, result = -1;
1164 struct hostent *he; 1343 struct sockaddr_storage ip;
1165 struct in_addr *in, ip; 1344 struct addrinfo hints, *res, *p;
1345 struct sockaddr_in *sin;
1346 struct sockaddr_in6 *sin6;
1347
1348 switch (address_family) {
1349 case -1:
1350 /* -4 and -6 are not specified on cmdline */
1351 address_family = AF_INET;
1352 sin = (struct sockaddr_in *)&ip;
1353 result = inet_pton(address_family, arg, &sin->sin_addr);
1354#ifdef USE_IPV6
1355 if( result != 1 ){
1356 address_family = AF_INET6;
1357 sin6 = (struct sockaddr_in6 *)&ip;
1358 result = inet_pton(address_family, arg, &sin6->sin6_addr);
1359 }
1360#endif
1361 /* If we don't find any valid addresses, we still don't know the address_family */
1362 if ( result != 1) {
1363 address_family = -1;
1364 }
1365 break;
1366 case AF_INET:
1367 sin = (struct sockaddr_in *)&ip;
1368 result = inet_pton(address_family, arg, &sin->sin_addr);
1369 break;
1370 case AF_INET6:
1371 sin6 = (struct sockaddr_in6 *)&ip;
1372 result = inet_pton(address_family, arg, &sin6->sin6_addr);
1373 break;
1374 default: crash("Address family not supported");
1375 }
1166 1376
1167 /* don't resolve if we don't have to */ 1377 /* don't resolve if we don't have to */
1168 if((ip.s_addr = inet_addr(arg)) != INADDR_NONE) { 1378 if(result == 1) {
1169 /* don't add all ip's if we were given a specific one */ 1379 /* don't add all ip's if we were given a specific one */
1170 return add_target_ip(arg, &ip); 1380 return add_target_ip(arg, &ip);
1171 /* he = gethostbyaddr((char *)in, sizeof(struct in_addr), AF_INET); */
1172 /* if(!he) return add_target_ip(arg, in); */
1173 } 1381 }
1174 else { 1382 else {
1175 errno = 0; 1383 errno = 0;
1176 he = gethostbyname(arg); 1384 memset(&hints, 0, sizeof(hints));
1177 if(!he) { 1385 if (address_family == -1) {
1386 hints.ai_family = AF_UNSPEC;
1387 } else {
1388 hints.ai_family = address_family == AF_INET ? PF_INET : PF_INET6;
1389 }
1390 hints.ai_socktype = SOCK_RAW;
1391 if((error = getaddrinfo(arg, NULL, &hints, &res)) != 0) {
1178 errno = 0; 1392 errno = 0;
1179 crash("Failed to resolve %s", arg); 1393 crash("Failed to resolve %s: %s", arg, gai_strerror(error));
1180 return -1; 1394 return -1;
1181 } 1395 }
1396 address_family = res->ai_family;
1182 } 1397 }
1183 1398
1184 /* possibly add all the IP's as targets */ 1399 /* possibly add all the IP's as targets */
1185 for(i = 0; he->h_addr_list[i]; i++) { 1400 for(p = res; p != NULL; p = p->ai_next) {
1186 in = (struct in_addr *)he->h_addr_list[i]; 1401 memcpy(&ip, p->ai_addr, p->ai_addrlen);
1187 add_target_ip(arg, in); 1402 add_target_ip(arg, &ip);
1188 1403
1189 /* this is silly, but it works */ 1404 /* this is silly, but it works */
1190 if(mode == MODE_HOSTCHECK || mode == MODE_ALL) { 1405 if(mode == MODE_HOSTCHECK || mode == MODE_ALL) {
@@ -1193,6 +1408,7 @@ add_target(char *arg)
1193 } 1408 }
1194 break; 1409 break;
1195 } 1410 }
1411 freeaddrinfo(res);
1196 1412
1197 return 0; 1413 return 0;
1198} 1414}
@@ -1203,7 +1419,7 @@ set_source_ip(char *arg)
1203 struct sockaddr_in src; 1419 struct sockaddr_in src;
1204 1420
1205 memset(&src, 0, sizeof(src)); 1421 memset(&src, 0, sizeof(src));
1206 src.sin_family = AF_INET; 1422 src.sin_family = address_family;
1207 if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE) 1423 if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE)
1208 src.sin_addr.s_addr = get_ip_address(arg); 1424 src.sin_addr.s_addr = get_ip_address(arg);
1209 if(bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1) 1425 if(bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1)
@@ -1214,20 +1430,26 @@ set_source_ip(char *arg)
1214static in_addr_t 1430static in_addr_t
1215get_ip_address(const char *ifname) 1431get_ip_address(const char *ifname)
1216{ 1432{
1433 // TODO: Rewrite this so the function return an error and we exit somewhere else
1434 struct sockaddr_in ip;
1435 ip.sin_addr.s_addr = 0; // Fake initialization to make compiler happy
1217#if defined(SIOCGIFADDR) 1436#if defined(SIOCGIFADDR)
1218 struct ifreq ifr; 1437 struct ifreq ifr;
1219 struct sockaddr_in ip;
1220 1438
1221 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1); 1439 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
1440
1222 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 1441 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
1442
1223 if(ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1) 1443 if(ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1)
1224 crash("Cannot determine IP address of interface %s", ifname); 1444 crash("Cannot determine IP address of interface %s", ifname);
1445
1225 memcpy(&ip, &ifr.ifr_addr, sizeof(ip)); 1446 memcpy(&ip, &ifr.ifr_addr, sizeof(ip));
1226 return ip.sin_addr.s_addr;
1227#else 1447#else
1448 (void) ifname;
1228 errno = 0; 1449 errno = 0;
1229 crash("Cannot get interface IP address on this platform."); 1450 crash("Cannot get interface IP address on this platform.");
1230#endif 1451#endif
1452 return ip.sin_addr.s_addr;
1231} 1453}
1232 1454
1233/* 1455/*
@@ -1309,18 +1531,19 @@ get_threshold(char *str, threshold *th)
1309} 1531}
1310 1532
1311unsigned short 1533unsigned short
1312icmp_checksum(unsigned short *p, int n) 1534icmp_checksum(uint16_t *p, size_t n)
1313{ 1535{
1314 register unsigned short cksum; 1536 unsigned short cksum;
1315 register long sum = 0; 1537 long sum = 0;
1316 1538
1317 while(n > 1) { 1539 /* sizeof(uint16_t) == 2 */
1318 sum += *p++; 1540 while(n >= 2) {
1541 sum += *(p++);
1319 n -= 2; 1542 n -= 2;
1320 } 1543 }
1321 1544
1322 /* mop up the occasional odd byte */ 1545 /* mop up the occasional odd byte */
1323 if(n == 1) sum += (unsigned char)*p; 1546 if(n == 1) sum += *((uint8_t *)p -1);
1324 1547
1325 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ 1548 sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
1326 sum += (sum >> 16); /* add carry */ 1549 sum += (sum >> 16); /* add carry */
@@ -1347,6 +1570,8 @@ print_help(void)
1347 1570
1348 printf (" %s\n", "-H"); 1571 printf (" %s\n", "-H");
1349 printf (" %s\n", _("specify a target")); 1572 printf (" %s\n", _("specify a target"));
1573 printf (" %s\n", "[-4|-6]");
1574 printf (" %s\n", _("Use IPv4 (default) or IPv6 to communicate with the targets"));
1350 printf (" %s\n", "-w"); 1575 printf (" %s\n", "-w");
1351 printf (" %s", _("warning threshold (currently ")); 1576 printf (" %s", _("warning threshold (currently "));
1352 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl); 1577 printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000, warn.pl);
diff --git a/plugins-root/pst3.c b/plugins-root/pst3.c
index c3589f0a..1f69f3a6 100644
--- a/plugins-root/pst3.c
+++ b/plugins-root/pst3.c
@@ -257,6 +257,6 @@ void usage() {
257 printf("\tRSS - Real memory usage (kilobytes)\n"); 257 printf("\tRSS - Real memory usage (kilobytes)\n");
258 printf("\t%%CPU - CPU usage\n"); 258 printf("\t%%CPU - CPU usage\n");
259 printf("\tCOMMAND - Command being run\n"); 259 printf("\tCOMMAND - Command being run\n");
260 printf("\tARGS - Full command line with arguements\n"); 260 printf("\tARGS - Full command line with arguments\n");
261 return; 261 return;
262} 262}
diff --git a/plugins-root/t/check_dhcp.t b/plugins-root/t/check_dhcp.t
index 222f4544..ce627736 100644
--- a/plugins-root/t/check_dhcp.t
+++ b/plugins-root/t/check_dhcp.t
@@ -19,7 +19,7 @@ if ($allow_sudo eq "yes" or $> == 0) {
19my $sudo = $> == 0 ? '' : 'sudo'; 19my $sudo = $> == 0 ? '' : 'sudo';
20 20
21my $successOutput = '/OK: Received \d+ DHCPOFFER\(s\), \d+ of 1 requested servers responded, max lease time = \d+ sec\./'; 21my $successOutput = '/OK: Received \d+ DHCPOFFER\(s\), \d+ of 1 requested servers responded, max lease time = \d+ sec\./';
22my $failureOutput = '/CRITICAL: No DHCPOFFERs were received/'; 22my $failureOutput = '/CRITICAL: (No DHCPOFFERs were received|Received \d+ DHCPOFFER\(s\), 0 of 1 requested servers responded, max lease time = \d+ sec\.)/';
23my $invalidOutput = '/Invalid hostname/'; 23my $invalidOutput = '/Invalid hostname/';
24 24
25my $host_responsive = getTestParameter( "NP_HOST_DHCP_RESPONSIVE", 25my $host_responsive = getTestParameter( "NP_HOST_DHCP_RESPONSIVE",
@@ -36,7 +36,12 @@ my $hostname_invalid = getTestParameter( "NP_HOSTNAME_INVALID",
36 36
37# try to determince interface 37# try to determince interface
38my $interface = ''; 38my $interface = '';
39if(`ifconfig -a 2>/dev/null` =~ m/^(e\w*\d+)/mx and $1 ne 'eth0') { 39
40# find interface used for default route
41if (-x '/usr/sbin/ip' and `/usr/sbin/ip route get 1.1.1.1 2>/dev/null` =~ m/\sdev\s(\S+)/) {
42 $interface = "-i $1";
43}
44elsif (`ifconfig -a 2>/dev/null` =~ m/^(e\w*\d+)/mx and $1 ne 'eth0') {
40 $interface = ' -i '.$1; 45 $interface = ' -i '.$1;
41} 46}
42 47
diff --git a/plugins-root/t/check_icmp.t b/plugins-root/t/check_icmp.t
index e043d4ed..96addd3b 100644
--- a/plugins-root/t/check_icmp.t
+++ b/plugins-root/t/check_icmp.t
@@ -12,7 +12,7 @@ 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 => 16; 15 plan tests => 20;
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}
@@ -83,3 +83,14 @@ $res = NPTest->testCmd(
83is( $res->return_code, 2, "One of two host nonresponsive - two required" ); 83is( $res->return_code, 2, "One of two host nonresponsive - two required" );
84like( $res->output, $failureOutput, "Output OK" ); 84like( $res->output, $failureOutput, "Output OK" );
85 85
86$res = NPTest->testCmd(
87 "$sudo ./check_icmp -H $host_responsive -s 127.0.15.15 -w 10000ms,100% -c 10000ms,100% -n 1 -m 2"
88 );
89is( $res->return_code, 0, "IPv4 source_ip accepted" );
90like( $res->output, $successOutput, "Output OK" );
91
92$res = NPTest->testCmd(
93 "$sudo ./check_icmp -H $host_responsive -b 65507"
94 );
95is( $res->return_code, 0, "Try max packet size" );
96like( $res->output, $successOutput, "Output OK - Didn't overflow" );