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 0000000..c8d497b --- /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 | } | ||