diff options
Diffstat (limited to 'contrib')
| -rwxr-xr-x | contrib/check_traceroute.pl | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/contrib/check_traceroute.pl b/contrib/check_traceroute.pl new file mode 100755 index 00000000..c8d497b0 --- /dev/null +++ b/contrib/check_traceroute.pl | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | #!/usr/bin/perl | ||
| 2 | |||
| 3 | # $Id$ | ||
| 4 | |||
| 5 | # $Log$ | ||
| 6 | # Revision 1.1 2005/01/27 10:34:16 stanleyhopcroft | ||
| 7 | # Jon Meek's check_traceroute for Mon hacked by YT for Nagios. Prob pretty weak | ||
| 8 | # | ||
| 9 | |||
| 10 | use strict ; | ||
| 11 | |||
| 12 | use vars qw(%ERRORS $TIMEOUT) ; | ||
| 13 | use utils qw(%ERRORS $TIMEOUT &print_revision &support &usage) ; | ||
| 14 | |||
| 15 | sub print_help (); | ||
| 16 | sub print_usage (); | ||
| 17 | |||
| 18 | $ENV{'PATH'}='/bin:/usr/bin:/usr/sbin'; | ||
| 19 | |||
| 20 | my $PROGNAME = 'check_traceroute' ; | ||
| 21 | # delay units are millisecs. | ||
| 22 | my $MAX_INTERHOP_DELAY = 200 ; | ||
| 23 | my $MAX_HOPS = 30 ; | ||
| 24 | |||
| 25 | use Getopt::Std; | ||
| 26 | |||
| 27 | use vars qw($opt_H $opt_N $opt_r $opt_R $opt_T $opt_d $opt_h $opt_i $opt_v $opt_V) ; | ||
| 28 | |||
| 29 | getopts('i:H:N:R:T:dhrvV'); | ||
| 30 | # H, N, R, T, and i take parms, others are flags | ||
| 31 | |||
| 32 | do { print_help ; exit $ERRORS{OK}; } | ||
| 33 | if $opt_h ; | ||
| 34 | |||
| 35 | do { print_revision($PROGNAME, '$Revision$'); exit $ERRORS{OK}; } | ||
| 36 | if $opt_V ; | ||
| 37 | |||
| 38 | do { print_help; exit $ERRORS{OK}; } | ||
| 39 | unless $opt_R || $opt_r ; | ||
| 40 | |||
| 41 | do { print_help; exit $ERRORS{OK}; } | ||
| 42 | unless $opt_R =~ m| | ||
| 43 | (?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-)+ | ||
| 44 | \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} | ||
| 45 | |x | ||
| 46 | || $opt_r ; | ||
| 47 | |||
| 48 | my $should_be = $opt_R ; | ||
| 49 | # Set default timeout in seconds | ||
| 50 | my $TimeOut = $opt_T || $TIMEOUT; | ||
| 51 | |||
| 52 | my $max_interhop_delay = $opt_i || $MAX_INTERHOP_DELAY ; | ||
| 53 | my $max_hops = $opt_N || $MAX_HOPS ; | ||
| 54 | |||
| 55 | my $TRACEROUTE = '/usr/sbin/traceroute'; | ||
| 56 | |||
| 57 | my $TargetHost = $opt_H ; | ||
| 58 | |||
| 59 | print_help | ||
| 60 | unless $TargetHost ; | ||
| 61 | |||
| 62 | my ($route, $pid, $rta_list) = ( '', '', '' ); | ||
| 63 | my %ResultString = () ; | ||
| 64 | |||
| 65 | $SIG{ALRM} = sub { die "timeout" }; | ||
| 66 | |||
| 67 | eval { | ||
| 68 | |||
| 69 | alarm($TimeOut); | ||
| 70 | # XXXX Discarding STDERR _should_ reduce the risk | ||
| 71 | # of unexpected output but consequently, results for | ||
| 72 | # non existent hosts are stupid. However, why would you | ||
| 73 | # specify a route to a NX host, other than a typo ... | ||
| 74 | |||
| 75 | $pid = open(TR, "$TRACEROUTE -n $TargetHost 2>/dev/null |") | ||
| 76 | or do { | ||
| 77 | "Failed. Cannot fork \"$TRACEROUTE\": $!" ; | ||
| 78 | $ERRORS{UNKNOWN} ; | ||
| 79 | } ; | ||
| 80 | |||
| 81 | my $hops = 0 ; | ||
| 82 | while (<TR>) { | ||
| 83 | |||
| 84 | print $_ | ||
| 85 | if $opt_d; | ||
| 86 | |||
| 87 | if ( m|#\*\s+\*\s+\*| ) { | ||
| 88 | # Get * * * then give up | ||
| 89 | $route .= '*'; | ||
| 90 | # 13 = PIPE, prevents Broken Pipe Error, at least on Solaris | ||
| 91 | kill 13, $pid; | ||
| 92 | last; | ||
| 93 | } | ||
| 94 | # We will only pick up the first IP address listed on a line for now | ||
| 95 | # traceroute to csg.citec.com.au (203.9.184.12), 64 hops max, 44 byte packets | ||
| 96 | # 1 10.254.254.254 0.868 ms 0.728 ms 0.705 ms | ||
| 97 | # 2 192.168.9.1 1.240 ms 1.165 ms 1.191 ms | ||
| 98 | |||
| 99 | my ($ThisHopIP) = m|\s+(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\s+|; | ||
| 100 | my ($max_rta) = m|\d{1,3}\.\d{1,3}\.\d{1,3}\s+ (\d+\.\d+) ms| ; | ||
| 101 | |||
| 102 | $route .= $ThisHopIP . '-'; | ||
| 103 | $rta_list .= sprintf("%.1f", $max_rta) . '-' ; | ||
| 104 | |||
| 105 | if ( $opt_v ) { | ||
| 106 | chomp $_ ; | ||
| 107 | print $_, ' ' x (58 - length), $route, "\n"; | ||
| 108 | } | ||
| 109 | |||
| 110 | $hops++ ; | ||
| 111 | |||
| 112 | if ( ($hops >= $max_hops) && ! $opt_r ) { | ||
| 113 | kill 13, $pid ; | ||
| 114 | print qq(Failed. Max hops ($max_hops) exceeeded: incomplete after $hops hops, "$route".\n) ; | ||
| 115 | exit $ERRORS{CRITICAL} ; | ||
| 116 | } | ||
| 117 | if ( ($hops %2 == 0) && ($hops >= 4) && ! $opt_r ) { | ||
| 118 | |||
| 119 | # Check for 2 cycles at end of path ie -(a-b)-(a-b)$ | ||
| 120 | # where a and b are IP v4 addresses of IS (routers). | ||
| 121 | |||
| 122 | my ($last_2_is) = $route =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}-\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})-$/ ; | ||
| 123 | if ( $route =~ /$last_2_is-$last_2_is-$/ ) { | ||
| 124 | kill 13, $pid ; | ||
| 125 | print qq(Failed. Last 2 routers ($last_2_is) repeated, "$route".\n) ; | ||
| 126 | exit $ERRORS{CRITICAL} ; | ||
| 127 | } | ||
| 128 | |||
| 129 | } | ||
| 130 | |||
| 131 | } | ||
| 132 | }; | ||
| 133 | |||
| 134 | alarm(0); | ||
| 135 | |||
| 136 | if ( $@ and $@ =~ /timeout/ ) { | ||
| 137 | $route .= '*'; | ||
| 138 | # It was a traceroute timeout | ||
| 139 | kill 13, $pid; | ||
| 140 | } elsif ( $@ and $@ !~ /timeout/ ) { | ||
| 141 | close TR ; | ||
| 142 | print "Failed. Somethings gone wrong with \"$TRACEROUTE\": $!" ; | ||
| 143 | exit $ERRORS{UNKNOWN} ; | ||
| 144 | } | ||
| 145 | |||
| 146 | close TR; | ||
| 147 | # Remove trailing '-'s | ||
| 148 | # $route =~ s/\-$//; | ||
| 149 | chop($route) ; | ||
| 150 | chop($rta_list) ; | ||
| 151 | |||
| 152 | print "$route\n" | ||
| 153 | if $opt_d; | ||
| 154 | |||
| 155 | if ( $opt_r ) { | ||
| 156 | print qq(Ok. Traceroute to host "$TargetHost" via route "$route".\n) ; | ||
| 157 | exit $ERRORS{OK}; | ||
| 158 | } | ||
| 159 | |||
| 160 | if ( &RouteEqual($should_be, $route) ) { | ||
| 161 | print qq(Ok. Traceroute to "$TargetHost" via expected route "$route" ($rta_list).\n) ; | ||
| 162 | exit $ERRORS{OK}; | ||
| 163 | } else { | ||
| 164 | print qq(Failed. Route "$route" ne expected "$should_be".\n) ; | ||
| 165 | exit $ERRORS{CRITICAL}; | ||
| 166 | } | ||
| 167 | |||
| 168 | |||
| 169 | sub RouteEqual { | ||
| 170 | my ($current_route, $prev_route) = @_; | ||
| 171 | return $current_route eq $prev_route ; | ||
| 172 | } | ||
| 173 | |||
| 174 | sub print_usage () { | ||
| 175 | print "Usage: $PROGNAME [ -R <route_string>|-r ] [ -d -T timeout -v -h -i ] -H <host>\n"; | ||
| 176 | } | ||
| 177 | |||
| 178 | sub print_help () { | ||
| 179 | print_revision($PROGNAME, '$Revision$') ; | ||
| 180 | print "Copyright (c) 2004 J Meek/Karl DeBisschop | ||
| 181 | |||
| 182 | This plugin checks whether traceroute to the destination succeeds and if so that the route string option (-R) matches the list of routers | ||
| 183 | returned by traceroute. | ||
| 184 | |||
| 185 | "; | ||
| 186 | print_usage(); | ||
| 187 | print " | ||
| 188 | -d | ||
| 189 | Debug | ||
| 190 | -h | ||
| 191 | Help | ||
| 192 | -i | ||
| 193 | _TODO_ | ||
| 194 | Max inter-hop delay (msec). | ||
| 195 | -H | ||
| 196 | Host. | ||
| 197 | -N | ||
| 198 | Max number of hops. | ||
| 199 | -r | ||
| 200 | Record current route (and output to STDOUT). Useful for getting the value of -R option ... | ||
| 201 | -v | ||
| 202 | Greater verbosity. | ||
| 203 | -R | ||
| 204 | Mandatory route string ie r1-r2-... where ri is the ip address of the ith router. | ||
| 205 | -T | ||
| 206 | Maximum time (seconds) to wait for the traceroute command to complete. Defaults to $TIMEOUT seconds. | ||
| 207 | |||
| 208 | "; | ||
| 209 | support(); | ||
| 210 | } | ||
