Code

Added support for --extra-opts in all C plugins (disabled by default, see configure...
[nagiosplug.git] / plugins-root / check_icmp.c
index 1ddc7561947fa633e7d273eebd434f8d9a5afed3..f3e5f0d3242414dda9779794df0d442aebdb5a1d 100644 (file)
@@ -1,43 +1,40 @@
- /******************************************************************************
-*
+/*****************************************************************************
+* 
 * Nagios check_icmp plugin
-*
+* 
 * License: GPL
-* Copyright (c) 2005-2007 nagios-plugins team
-*
+* Copyright (c) 2005-2008 Nagios Plugins Development Team
 * Original Author : Andreas Ericsson <ae@op5.se>
-*
+* 
 * Last Modified: $Date$
-*
+* 
 * Description:
-*
+* 
 * This file contains the check_icmp plugin
-*
-*  Relevant RFC's: 792 (ICMP), 791 (IP)
-*
-*  This program was modeled somewhat after the check_icmp program,
-*  which was in turn a hack of fping (www.fping.org) but has been
-*  completely rewritten since to generate higher precision rta values,
-*  and support several different modes as well as setting ttl to control.
-*  redundant routes. The only remainders of fping is currently a few
-*  function names.
-*
-* License Information:
-*
-* This program is free software; you can redistribute it and/or modify
+* 
+* Relevant RFC's: 792 (ICMP), 791 (IP)
+* 
+* This program was modeled somewhat after the check_icmp program,
+* which was in turn a hack of fping (www.fping.org) but has been
+* completely rewritten since to generate higher precision rta values,
+* and support several different modes as well as setting ttl to control.
+* redundant routes. The only remainders of fping is currently a few
+* function names.
+* 
+* 
+* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
+* the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
-*
+* 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
-*
+* 
 * You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+* 
 * $Id$
 * 
 *****************************************************************************/
@@ -46,7 +43,7 @@
 /* char *progname = "check_icmp"; */
 char *progname;
 const char *revision = "$Revision$";
-const char *copyright = "2005-2007";
+const char *copyright = "2005-2008";
 const char *email = "nagiosplug-devel@lists.sourceforge.net";
 
 /** nagios plugins basic includes */
@@ -192,7 +189,7 @@ 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 *);
+static int handle_random_icmp(char *, struct sockaddr_in *);
 static unsigned short icmp_checksum(unsigned short *, int);
 static void finish(int);
 static void crash(const char *, ...);
@@ -242,10 +239,10 @@ crash(const char *fmt, ...)
 }
 
 
-static char *
+static const char *
 get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
 {
-       char *msg = "unreachable";
+       const char *msg = "unreachable";
 
        if(debug > 1) printf("get_icmp_error_msg(%u, %u)\n", icmp_type, icmp_code);
        switch(icmp_type) {
@@ -299,19 +296,18 @@ get_icmp_error_msg(unsigned char icmp_type, unsigned char icmp_code)
 }
 
 static int
-handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
+handle_random_icmp(char *packet, struct sockaddr_in *addr)
 {
-       struct icmp sent_icmp;
+       struct icmp p, sent_icmp;
        struct rta_host *host = NULL;
-       unsigned char *ptr;
 
-       if(p->icmp_type == ICMP_ECHO && p->icmp_id == pid) {
+       memcpy(&p, packet, sizeof(p));
+       if(p.icmp_type == ICMP_ECHO && p.icmp_id == pid) {
                /* echo request from us to us (pinging localhost) */
                return 0;
        }
 
-       ptr = (unsigned char *)p;
-       if(debug) printf("handle_random_icmp(%p, %p)\n", (void *)p, (void *)addr);
+       if(debug) printf("handle_random_icmp(%p, %p)\n", (void *)&p, (void *)addr);
 
        /* only handle a few types, since others can't possibly be replies to
         * us in a sane network (if it is anyway, it will be counted as lost
@@ -323,15 +319,15 @@ handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
         * TIMXCEED actually sends a proper icmp response we will have passed
         * too many hops to have a hope of reaching it later, in which case it
         * indicates overconfidence in the network, poor routing or both. */
-       if(p->icmp_type != ICMP_UNREACH && p->icmp_type != ICMP_TIMXCEED &&
-          p->icmp_type != ICMP_SOURCEQUENCH && p->icmp_type != ICMP_PARAMPROB)
+       if(p.icmp_type != ICMP_UNREACH && p.icmp_type != ICMP_TIMXCEED &&
+          p.icmp_type != ICMP_SOURCEQUENCH && p.icmp_type != ICMP_PARAMPROB)
        {
                return 0;
        }
 
        /* might be for us. At least it holds the original package (according
         * to RFC 792). If it isn't, just ignore it */
-       memcpy(&sent_icmp, ptr + 28, sizeof(sent_icmp));
+       memcpy(&sent_icmp, packet + 28, sizeof(sent_icmp));
        if(sent_icmp.icmp_type != ICMP_ECHO || sent_icmp.icmp_id != pid ||
           sent_icmp.icmp_seq >= targets)
        {
@@ -343,7 +339,7 @@ handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
        host = table[sent_icmp.icmp_seq];
        if(debug) {
                printf("Received \"%s\" from %s for ICMP ECHO sent to %s.\n",
-                          get_icmp_error_msg(p->icmp_type, p->icmp_code),
+                          get_icmp_error_msg(p.icmp_type, p.icmp_code),
                           inet_ntoa(addr->sin_addr), host->name);
        }
 
@@ -354,7 +350,7 @@ handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
 
        /* source quench means we're sending too fast, so increase the
         * interval and mark this packet lost */
-       if(p->icmp_type == ICMP_SOURCEQUENCH) {
+       if(p.icmp_type == ICMP_SOURCEQUENCH) {
                pkt_interval *= pkt_backoff_factor;
                target_interval *= target_backoff_factor;
        }
@@ -362,8 +358,8 @@ handle_random_icmp(struct icmp *p, struct sockaddr_in *addr)
                targets_down++;
                host->flags |= FLAG_LOST_CAUSE;
        }
-       host->icmp_type = p->icmp_type;
-       host->icmp_code = p->icmp_code;
+       host->icmp_type = p.icmp_type;
+       host->icmp_code = p.icmp_code;
        host->error_addr.s_addr = addr->sin_addr.s_addr;
 
        return 0;
@@ -382,7 +378,7 @@ main(int argc, char **argv)
        setlocale (LC_ALL, "");
        bindtextdomain (PACKAGE, LOCALEDIR);
        textdomain (PACKAGE);
-       
+
        /* print a helpful error message if geteuid != 0 */
        np_warn_if_not_root();
 
@@ -451,6 +447,9 @@ main(int argc, char **argv)
                packets = 5;
        }
 
+       /* Parse extra opts if any */
+       argv=np_extra_opts(&argc, argv, progname);
+
        /* parse the arguments */
        for(i = 1; i < argc; i++) {
                while((arg = getopt(argc, argv, "vhVw:c:n:p:t:H:s:i:b:I:l:m:")) != EOF) {
@@ -650,7 +649,7 @@ run_checks()
                                                                 table[t]->name);
                                continue;
                        }
-                       
+
                        /* we're still in the game, so send next packet */
                        (void)send_icmp_ping(icmp_sock, table[t]);
                        result = wait_for_reply(icmp_sock, target_interval);
@@ -758,13 +757,13 @@ wait_for_reply(int sock, u_int t)
                memcpy(&icp, buf + hlen, sizeof(icp));
 
                if(icp.icmp_id != pid) {
-                       handle_random_icmp(&icp, &resp_addr);
+                       handle_random_icmp(buf + hlen, &resp_addr);
                        continue;
                }
 
                if(icp.icmp_type != ICMP_ECHOREPLY || icp.icmp_seq >= targets) {
                        if(debug > 2) printf("not a proper ICMP_ECHOREPLY\n");
-                       handle_random_icmp(&icp, &resp_addr);
+                       handle_random_icmp(buf + hlen, &resp_addr);
                        continue;
                }
 
@@ -897,7 +896,7 @@ finish(int sig)
        unsigned char pl;
        double rta;
        struct rta_host *host;
-       char *status_string[] =
+       const char *status_string[] =
        {"OK", "WARNING", "CRITICAL", "UNKNOWN", "DEPENDENT"};
        int hosts_ok = 0;
        int hosts_warn = 0;
@@ -1111,7 +1110,7 @@ add_target(char *arg)
 
                /* this is silly, but it works */
                if(mode == MODE_HOSTCHECK || mode == MODE_ALL) {
-                       printf("mode: %d\n", mode);
+                       if(debug > 2) printf("mode: %d\n", mode);
                        continue;
                }
                break;
@@ -1139,12 +1138,14 @@ get_ip_address(const char *ifname)
 {
 #if defined(SIOCGIFADDR)
        struct ifreq ifr;
+       struct sockaddr_in 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);
-       return ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
+       memcpy(&ip, &ifr.ifr_addr, sizeof(ip));
+       return ip.sin_addr.s_addr;
 #else
        errno = 0;
        crash("Cannot get interface IP address on this platform.");
@@ -1255,16 +1256,17 @@ print_help(void)
 {
 
   /*print_revision (progname, revision);*/ /* FIXME: Why? */
-  
+
   printf ("Copyright (c) 2005 Andreas Ericsson <ae@op5.se>\n");
   printf (COPYRIGHT, copyright, email);
-  
+
   printf ("\n\n");
-  
+
   print_usage ();
-  
+
   printf (_(UT_HELP_VRSN));
-  
+  printf (_(UT_EXTRA_OPTS));
+
   printf (" %s\n", "-H");
   printf ("    %s\n", _("specify a target"));
   printf (" %s\n", "-w");
@@ -1299,23 +1301,28 @@ print_help(void)
   printf ("    %s\n", _("verbose"));
 
   printf ("\n");
-       printf ("%s\n\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
-  printf ("%s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
-  printf ("%s\n", _("packet loss.  The default values should work well for most users."));
-  printf ("%s\n", _("You can specify different RTA factors using the standardized abbreviations"));
-  printf ("%s\n\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds."));
+  printf ("%s\n", _("Notes:"));
+  printf (" %s\n", _("The -H switch is optional. Naming a host (or several) to check is not."));
+  printf ("\n");
+  printf (" %s\n", _("Threshold format for -w and -c is 200.25,60% for 200.25 msec RTA and 60%"));
+  printf (" %s\n", _("packet loss.  The default values should work well for most users."));
+  printf (" %s\n", _("You can specify different RTA factors using the standardized abbreviations"));
+  printf (" %s\n", _("us (microseconds), ms (milliseconds, default) or just plain s for seconds."));
 /* -d not yet implemented */
 /*  printf ("%s\n", _("Threshold format for -d is warn,crit.  12,14 means WARNING if >= 12 hops"));
   printf ("%s\n", _("are spent and CRITICAL if >= 14 hops are spent."));
   printf ("%s\n\n", _("NOTE: Some systems decrease TTL when forming ICMP_ECHOREPLY, others do not."));*/
-  printf ("%s\n\n", _("The -v switch can be specified several times for increased verbosity."));
-
+  printf ("\n");
+  printf (" %s\n", _("The -v switch can be specified several times for increased verbosity."));
 /*  printf ("%s\n", _("Long options are currently unsupported."));
   printf ("%s\n", _("Options marked with * require an argument"));
 */
+#ifdef NP_EXTRA_OPTS
+  printf ("\n");
+  printf (_(UT_EXTRA_OPTS_NOTES));
+#endif
+
   printf (_(UT_SUPPORT));
-  
-  printf (_(UT_NOWARRANTY));
 }
 
 
@@ -1324,5 +1331,5 @@ void
 print_usage (void)
 {
   printf (_("Usage:"));
-  printf(" %s [options] [-H] host1 host2 hostn\n", progname);
+  printf(" %s [options] [-H] host1 host2 hostN\n", progname);
 }