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