[Nagiosplug-devel] Fwd: Patch proposal for check_icmp

Holger Weiss holger at CIS.FU-Berlin.DE
Thu Dec 20 20:48:12 CET 2007


* Patrick Cervicek <patrick.postfix at cervicek.de> [2007-12-20 20:27]:
> Ton Voon schrieb:
> > I got this email from Harald re: check_icmp specifying a source  
> > address. I don't know too much about check_icmp, so can anyone else  
> > look over this?

Looks fine to me (apart from the fact that it won't work with IPv6, but
check_icmp currently doesn't support IPv6 anyway; we should fix this
sometime).  I cleaned things up a bit and added the possibility to
specify interface names (which doesn't require root-privileges).  If
nobody objects, I'll commit the attached version of the patch.

> > +#include <netinet/in.h>
>
> 1) in.h is already included 5 lines higher. Is this #include necessary? 

No.

> > +		if (bind(icmp_sock, (struct sockaddr *) &src, sizeof(struct sockaddr_un)) == -1) {
>
> 2) Wouldn't it better to check before, if 'icmp_sock' or 'sockets' is >0 ?

That's not necessary.  If icmp_sock wasn't created the bind(2) call will
fail and the plugin will spit out an error message such as "check_icmp:
Cannot bind to IP address 127.0.0.1: Bad file descriptor".

> 3) Is 'sizeof(struct sockaddr_UN)' good?

Nope.

Thanks to Harald for the patch and thanks to Patrick for looking into
it!

Holger
-------------- next part --------------
Index: check_icmp.c
===================================================================
--- check_icmp.c	(revision 1880)
+++ check_icmp.c	(working copy)
@@ -54,6 +54,7 @@
 #include "netutils.h"
 #include "utils.h"
 
+#include <sys/ioctl.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <stdio.h>
@@ -66,6 +67,7 @@
 #include <ctype.h>
 #include <netdb.h>
 #include <sys/socket.h>
+#include <net/if.h>
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
@@ -178,11 +180,13 @@
 void print_usage (void);
 static u_int get_timevar(const char *);
 static u_int get_timevaldiff(struct timeval *, struct timeval *);
+static in_addr_t get_ip_address(const char *);
 static int wait_for_reply(int, u_int);
 static int recvfrom_wto(int, char *, unsigned int, struct sockaddr *, u_int *);
 static int send_icmp_ping(int, struct rta_host *);
 static int get_threshold(char *str, threshold *th);
 static void run_checks(void);
+static void set_source_ip(char *);
 static int add_target(char *);
 static int add_target_ip(char *, struct in_addr *);
 static int handle_random_icmp(struct icmp *, struct sockaddr_in *);
@@ -446,7 +450,7 @@
 
 	/* parse the arguments */
 	for(i = 1; i < argc; i++) {
-		while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:i:b:I:l:m:")) != EOF) {
+		while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:S:i:b:I:l:m:")) != EOF) {
 			switch(arg) {
 			case 'v':
 				debug++;
@@ -489,6 +493,9 @@
 					crit_down = (unsigned char)strtoul(ptr + 1, NULL, 0);
 				}
 				break;
+			case 'S': /* specify source ip for ping */
+				set_source_ip(optarg);
+				break;
       case 'V':                 /* version */
         /*print_revision (progname, revision);*/ /* FIXME: Why? */
         exit (STATE_OK);
@@ -1109,6 +1116,40 @@
 
 	return 0;
 }
+
+static void
+set_source_ip(char *arg)
+{
+	struct sockaddr_in src;
+
+	memset(&src, 0, sizeof(src));
+	src.sin_family = AF_INET;
+	if((src.sin_addr.s_addr = inet_addr(arg)) == INADDR_NONE)
+		src.sin_addr.s_addr = get_ip_address(arg);
+	if (bind(icmp_sock, (struct sockaddr *)&src, sizeof(src)) == -1)
+		crash("Cannot bind to IP address %s", arg);
+}
+
+/* TODO: Move this to netutils.c and also change check_dhcp to use that. */
+static in_addr_t
+get_ip_address(const char *ifname)
+{
+#if defined(SIOCGIFADDR)
+	struct ifreq ifr;
+	struct in_addr ip;
+
+	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
+	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+	if (ioctl(icmp_sock, SIOCGIFADDR, &ifr) == -1)
+		crash("Cannot determine IP address of interface %s", ifname);
+	ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
+	return ip.s_addr;
+#else
+	errno = 0;
+	crash("Cannot get interface IP address on this platform.");
+#endif
+}
+
 /*
  * u = micro
  * m = milli
@@ -1225,6 +1266,8 @@
   
   printf (" %s\n", "-H");
   printf ("    %s\n", _("specify a target"));
+  printf (" %s\n", "-S");
+  printf ("    %s\n", _("specify a source IP address or device name"));
   printf (" %s\n", "-w");
   printf ("    %s", _("warning threshold (currently "));
   printf ("%0.3fms,%u%%)\n", (float)warn.rta / 1000 , warn.pl / 1000);


More information about the Devel mailing list