check_traceroute.pl 5.0 KB

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