check_traceroute.pl 5.1 KB

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