# $Header: traceroute.pl 03-jun-2008.13:04:22 qding Exp $ # # traceroute.pl # # Copyright (c) 2002, 2008, Oracle. All rights reserved. # # NAME # traceroute.pl - # # DESCRIPTION # # # NOTES # Comment 1 - The if condition referred to by this comment SHOULD NOT have # it's elements' order changed. This is so that we are conservative. The # purpose is to use the traceroute_success flag as last resource to decide # if a traceroute failed or not. This was only added to overcome the bug # where certain nodes don't have the same name or IP as reported by # traceroute in the starting of the output. # # MODIFIED (MM/DD/YY) # qding 06/03/08 - bug 7144627, remove references to internal # identifiers # mfidanbo 07/07/06 - Backport mfidanbo_bug-4867135 from main # mfidanbo 06/28/06 - Fix no hostname issue on windows. # afontana 02/24/05 - dont make ttl go over 255 # afontana 02/09/05 - fix regex to catch * before host not found # afontana 01/29/05 - account for multiple host names # skumar 05/25/04 - MAC OS X changes + fix osVer # nsharma 05/24/04 - fix uname command # nsharma 05/24/04 - merge forward from 10.1.0.2 # asawant 02/13/02 - NT Porting # sravindh 05/01/04 - Fixes for internal error in tvmlb tests # sravindh 04/29/04 - Fix variable name # sravindh 04/29/04 - Include OSF1 in traceroute action # nsharma 04/27/04 - Fix for AIX # vsekuboy 06/25/03 - Removed extra } at line 102 # vsekuboy 05/22/03 - Changes for HP and Linux during EM 4.0.0 # asawant 04/01/03 - Fixing ping params # asawant 12/06/02 - Fixing misspelling # asawant 11/26/02 - Fixing security breach # xxu 06/25/02 - remove /usr/local/bin/perl # asawant 05/13/02 - Bug: traceroute name/IP are not the actual final # ones. # asawant 03/26/02 - Adding ping verbose.. # asawant 03/25/02 - asawant_dev_traceroute_020312 # asawant 03/12/02 - Creation # use IO::Handle; use strict; use Getopt::Long; # set up to accept user input # The character used to merge the ttl and packet# into one key column my $keySepChar = ':'; my $successStr = 'Success'; my $noResponseStr = 'No response'; # Keep the original arguments around my @ARGV_CP = @ARGV; # Parse the input parameters and put them in the cmdLine hash table my %cmdLine = (); GetOptions(\%cmdLine, "txnname=s", "beaconname=s", "delimiter=s", "lineheader=s", "mode=i", "numpackets=i", "maxttl=i", "maxtime=i", "tracefile=s", "trace!"); my $traceFileOpen = 0; my $traceEnabled = 0; if(exists $cmdLine{"trace"}) { $traceEnabled = $cmdLine{"trace"}; } my $traceFile; if(exists $cmdLine{"tracefile"}) { $traceFile = $cmdLine{"tracefile"}; } else { $traceEnabled = 0; } trace("Arguments: @ARGV_CP\n"); #trace_arguments(\@ARGV_CP); trace("Env: $ENV{EM_TARGET_NAME}\n"); # mode can be: # 0 = simple ping, 1 = advanced ping, 2 = detailed ping, 3 = traceroute my $mode = 3; if(exists $cmdLine{"mode"}) { $mode = $cmdLine{"mode"}; if($mode < 2) { @ARGV = ('osresp.pl', '-txnname', $cmdLine{'txnname'}, '-beaconname', $cmdLine{'beaconname'}, '-mode', $cmdLine{'mode'}, '-numpackets', $cmdLine{'numpackets'}, '-maxttl', $cmdLine{'maxttl'}); require "osresp.pl"; trace("Should have exited in the osresp.pl call.\n"); print("em_error=Internal error."); exit 1; } } require "semd_common.pl"; my $target = $ENV{EM_TARGET_NAME}; #target we are checking on if(! defined($target) || ($target eq '')) { trace("em_error=Invalid target [$target]!"); print "em_error=Invalid target [$target]!"; exit 1; } trace("target: $target\n"); my $txnName = ''; if(exists $cmdLine{"txnname"}) { $txnName = $cmdLine{"txnname"}; } else { trace("em_error=Missing transaction name (-txnname)\n"); print "em_error=Missing transaction name (-txnname)\n"; exit 1; } my $beaconName = ''; if(exists $cmdLine{"beaconname"}) { $beaconName = $cmdLine{"beaconname"}; } else { trace("em_error=Missing beacon name (-beaconname)\n"); print "em_error=Missing beacon name (-beaconname)\n"; exit 1; } my $lineHeader = 'em_result='; #character used to seperate output columns if(exists $cmdLine{"lineheader"}) { $lineHeader = $cmdLine{"lineheader"}; } my $delimiter = '|'; #character used to seperate output columns if(exists $cmdLine{"delimiter"}) { $delimiter = $cmdLine{"delimiter"}; } my $numPackets = 1; # The number of packets to send out. if(exists $cmdLine{"numpackets"}) { $numPackets = $cmdLine{"numpackets"}; } my $maxTtl = 30; # Max number of hops. if(exists $cmdLine{"maxttl"}) { $maxTtl = $cmdLine{"maxttl"}; } my $maxTime = 5; # Max wait time per packet. if(exists $cmdLine{"maxtime"}) { $maxTime = $cmdLine{"maxtime"}; } my $osType; if(($osType = get_osType()) == -1) { # EMD_DEBUG("The OS is unsupported.\n", "$target"); trace("em_error=unsupported OS\n"); print "em_error=unsupported OS\n"; exit 1; } my $osVer = 'none'; if(!($osType eq "WIN")) { $osVer = `uname -r`; chomp($osVer); } if($mode == 4) # ping verbose { #doPingVerbose(); exit 0; } # Make sure this is a target name (security provision) # For this we check for any space in the string (including new line) and # then if this is a valid hostname (1.2.3.4 is a valid hostname too) if(($target =~ m/\s+/o) || (!gethostbyname("$target"))) { #EMD_DEBUG("Invalid hostname: $!", "$target"); trace("em_error=Invalid hostname."); print "em_error=Invalid hostname."; # This is so that the interactive UI picks up the error message print "em_error=traceroute: unknown host: $target "; exit 1; } my $r; if ($osType eq "SOL" || $osType eq "HP" || $osType eq "LNX" || $osType eq "AIX" || $osType eq "OSF1" || $osType eq "MAC OS X") { # EMD_TRACE("Getting traceroute for Sun OS.\n"); $ENV{'PATH'} = "/bin:/usr/contrib/bin:/usr/bin:/usr/sbin:/usr/local/bin:/local/bin"; trace("traceroute -m $maxTtl -w $maxTime -q $numPackets $target\n"); if($maxTtl > 0 && $maxTtl < 255) # If not, then traceroute will throw adequate error { # always allow for the collection of one more line then the user requested $maxTtl++; } if ($osType eq "AIX") { trace("traceroute -m $maxTtl -w $maxTime -q $numPackets $target | grep -v trying | grep -v source\n"); $r = `traceroute -m $maxTtl -w $maxTime -q $numPackets $target | grep -v trying | grep -v source"`; } else { if ($osVer eq "B.11.00") { trace("traceroute -m $maxTtl -w $maxTime $target -q $numPackets\n"); $r = `traceroute -m $maxTtl -w $maxTime $target -q $numPackets`; } else { trace("traceroute -m $maxTtl -w $maxTime -q $numPackets $target\n"); $r = `traceroute -m $maxTtl -w $maxTime -q $numPackets $target`; } } if(!$r) { #EMD_DEBUG("Failed to execute traceroute: $!", "$target"); trace("em_error=Failed to execute traceroute."); print "em_error=Failed to execute traceroute."; exit 1; } # reset maxTtl to the number of lines the user requested $maxTtl--; } elsif ($osType eq "WIN") { # Time is in msec on Windows $maxTime = $maxTime * 1000; # Num Packets not supported on WIN! trace("tracert -h $maxTtl -w $maxTime $target\n"); if($maxTtl > 0) # If not, then traceroute will throw adequate error { # always allow for the collection of one more line then the user requested $maxTtl++; } $r = `tracert -h $maxTtl -w $maxTime $target`; if(!$r) { #EMD_DEBUG("Failed to execute traceroute: $!", "$target"); trace("em_error=Failed to execute traceroute."); print "em_error=Failed to execute traceroute."; exit 1; } # reset maxTtl to the number of lines the user requested $maxTtl--; # reset maxTime to the time the user requested $maxTime = $maxTime / 1000; } else { trace("em_error=Platform port not implemented."); print "em_error=Platform port not implemented."; exit 1; } trace("All lines: \n$r\n"); # Split the lines my @resLns = split(m/\n/o, $r); if ($osType eq "OSF1") { shift @resLns; } if(@resLns < 1) { trace("em_error=No lines returned."); print "em_error=No lines returned."; exit 1; } my $traceroute_success = 1; # On Windows we get 6 lines extra (information lines) if ($osType eq "WIN") { if(@resLns < 7) # Just in case.. { trace("em_error=Bad number of lines."); print "em_error=Bad output!"; exit ; } #assign $target to the IP address (in case of differing DNS) my $targetIP; my $comparison = '.*\[(\d+\.\d+\.\d+\.\d+)\].*'; if(($targetIP) = $resLns[1] =~ m/$comparison/o){ $target = $targetIP; } #remove the first 4 lines from the array splice(@resLns, 0, 4); #remove the last 2 lines from the array splice(@resLns, @resLns - 2, 2); trace("Array: '@resLns'\n"); } if(@resLns > $maxTtl) { #remove the last line from the array (we have collected 1 extra line) pop(@resLns); $traceroute_success = 0; } my @resultTbl = (); if($mode == 2) { my $time = 0; my $status; my $lastHost; my $ttl; my $dropRate = 0; my $successCnt; # ttl, packetNum, intermediatHostName, intermediateHostIp, time, status; parsePrintLine($resLns[@resLns - 1], \@resultTbl, \$successCnt); my $tmpHost = $resultTbl[0]->[2]; my $tmpIp = $resultTbl[0]->[3]; if($successCnt == 0) { $traceroute_success = 0; } $ttl = $resultTbl[0]->[0]; trace("tmpHost: $tmpHost ; target: $target\n"); # please refer to comment 1 before making ANY changes in the branch below if(($tmpHost ne '') && (($tmpHost =~ m/$target((\..*)|($))/io) || ($target =~ m/$tmpIp/io) || ($traceroute_success))) # success { trace("Success; tmpHost: $tmpHost ; target: $target\n"); $status = 1; if($resultTbl[0]->[5] ne "$successStr") { $dropRate++; trace("dropRate: $dropRate\n"); } else { $time = $resultTbl[0]->[4]; } my $j = 0; for($j++; $j < $numPackets; $j++) { trace("j: $j, status: $resultTbl[$j]->[5]\n"); if($resultTbl[$j]->[5] ne "$successStr") { $dropRate++; trace("dropRate: $dropRate\n"); } else { $time += $resultTbl[$j]->[4]; } } trace("j: $j, time: $time, dropRate: $dropRate\n"); $time = $time / ($numPackets - $dropRate); $dropRate = $dropRate * 100 / $numPackets; $time = sprintf("%.2f", $time); $dropRate = sprintf("%.2f", $dropRate); } else # failure { trace("Failure;\n"); trace("Failure; tmpHost: '$tmpHost' ; target: '$target'\n"); my $j = 2; $time = ''; $status = 0; $dropRate = '100'; $lastHost = $tmpHost; while(($lastHost eq '') && ($j <= @resLns)) { @resultTbl = (); parsePrintLine($resLns[@resLns - $j], \@resultTbl); my $i; for($i = 0; ($i < @resultTbl) && ($lastHost eq ''); $i++) { $lastHost = $resultTbl[$i]->[2]; } $j++; } my $tmpCnt = @resultTbl; trace("lastHost: $lastHost ; j: $j ; resLns: $tmpCnt\n"); } trace("$lineHeader" . "$txnName" . "$delimiter" . "$beaconName" . "$delimiter" . "$time" . "$delimiter" . "$status" . "$delimiter" . "$dropRate" . "$delimiter" . "$ttl" . "$delimiter" . "$lastHost\n"); print("$lineHeader" . "$txnName" . "$delimiter" . "$beaconName" . "$delimiter" . "$time" . "$delimiter" . "$status" . "$delimiter" . "$dropRate" . "$delimiter" . "$ttl" . "$delimiter" . "$lastHost\n"); } else # mode 3 { my $i; for($i = 0; $i < @resLns; $i++) { parsePrintLine($resLns[$i], \@resultTbl); } # print all results to output for($i=0; $i < @resultTbl; $i++) { trace("$lineHeader" . "$txnName" . "$delimiter" . "$beaconName" . "$delimiter" . "$resultTbl[$i]->[0]$keySepChar$resultTbl[$i]->[1]" . "$delimiter" . "$resultTbl[$i]->[0]" . "$delimiter" . "$resultTbl[$i]->[1]" . "$delimiter" . "$resultTbl[$i]->[2]" . "$delimiter" . "$resultTbl[$i]->[3]" . "$delimiter" . "$resultTbl[$i]->[4]" . "$delimiter" . "$resultTbl[$i]->[5]\n"); print("$lineHeader" . "$txnName" . "$delimiter" . "$beaconName" . "$delimiter" . "$resultTbl[$i]->[0]$keySepChar$resultTbl[$i]->[1]" . "$delimiter" . "$resultTbl[$i]->[0]" . "$delimiter" . "$resultTbl[$i]->[1]" . "$delimiter" . "$resultTbl[$i]->[2]" . "$delimiter" . "$resultTbl[$i]->[3]" . "$delimiter" . "$resultTbl[$i]->[4]" . "$delimiter" . "$resultTbl[$i]->[5]\n"); } } exit 0; ############################################################################### # FUCTION DEFINITIONS ############################################################################### ############################################################################### sub trace { if($traceEnabled) { my ($string) = @_; if(!$traceFileOpen) { open tFile, ">$traceFile"; $traceFileOpen = 1; } autoflush tFile 1; print tFile $string; } } ############################################################################### ############################################################################### sub trace_arguments { my ($arg_ref) = (@_); my $i; for($i = 0; $i < @$arg_ref; $i++) { trace("Stack element $i: $arg_ref->[$i] \n"); } } ############################################################################### ############################################################################### # The following are some good test cases for the function below (SOLARIS). # $r is the function input # # $r = # '1 swi-1-rtr-1-453.example.com (127.0.1.1) 0.533 ms 0.395 ms' # . "\n" . # '2 swi-1-rtr-1-453.example.com (127.0.1.1) 0.407 ms !H *'; # # # $r = '1 USW-phx-gw.customer.ALTER.NET (137.39.162.10) 142.840 ms 151.245 ms 129.564 ms' # . "\n" . # '2 206.80.192.221 (206.80.192.221) 127.569 ms vdsla121.phnx.uswest.net (216.161.182.121) 185.214 ms *' # . "\n" . # '3 vdsla121.phnx.uswest.net (216.161.182.121) 442.912 ms 205.956 ms 221.537 ms' # . "\n" . # '4 vdsla121.phnx.uswest.net (216.161.182.121) 164.728 ms 186.997 ms 190.414 ms' # . "\n" . # '5 vdsla121.phnx.uswest.net (216.161.182.121) 306.964 ms 189.152 ms 221.288 ms'; # # # $r = '1 ebay-2-gw.customer.ALTER.NET (157.130.197.90) 114.204 ms 123.232 ms !H 120.957 ms' # . "\n" . # '2 10.1.2.5 (10.1.2.5) 110.693 ms 114.475 ms ! 107.747 ms' # . "\n" . # '3 * * *' # . "\n" . # '4 * * *' # . "\n" . # '5 ebay-2-gw.customer.ALTER.NET (157.130.197.90) 126.319 ms * *' # . "\n" . # '6 ebay-2-gw.customer.ALTER.NET (157.130.197.90) 114.204 ms * 199.000 ms !H'; # # # WINDOWS SAMPLE OUTPUT # $r = 'Tracing route to localhost.example.com [127.0.1.1]' # . "\n" . # 'over a maximum of 30 hops:' # . "\n" . # ' 1 <10 ms <10 ms <10 ms swi-2-rtr-1-v452.example.com [127.0.1.1]' # . "\n" . # ' 2 <10 ms <10 ms <10 ms swi-1-rtr-1-v254.example.com [127.0.1.1]' # . "\n" . # ' 3 <10 ms <10 ms <10 ms usrtr1-ge5-0-0.example.com [127.0.1.1]' # . "\n" . # ' 4 78 ms 78 ms 62 ms rtr-1-atm0-0-0-1.example.com [127.0.1.1]' # . "\n" . # ' 5 78 ms 78 ms 63 ms rtr-1-v111.example.com [127.0.1.1]' # . "\n" . # ' 6 78 ms 79 ms 62 ms foo.example.com [127.0.1.1]' # . "\n" . # 'Trace complete.'; # # # $r = # 'Tracing route to www.whitehouse.gov [198.137.240.92]' # . "\n" . # 'over a maximum of 30 hops:' # . "\n" . # '' # . "\n" . # ' 1 1 ms <10 ms 1 ms 10.215.3.1' # . "\n" . # ' 2 4 ms 2 ms 2 ms 129.71.200.254' # . "\n" . # ' 3 3 ms 4 ms 4 ms 129.71.200.1' # . "\n" . # ' 4 4 ms 4 ms 3 ms 129.71.254.1' # . "\n" . # ' 5 8 ms 8 ms 10 ms 207.68.7.18' # . "\n" . # ' 6 32 ms 34 ms 41 ms tu0.NORF.ba-dsg.net [209.158.31.249]' # . "\n" . # ' 7 43 ms 37 ms 41 ms wdc-core-02.inet.qwest.net [205.171.24.85]' # . "\n" . # ' 8 51 ms 58 ms 47 ms jfk-core-01.inet.qwest.net [205.171.5.233]' # . "\n" . # ' 9 59 ms 58 ms 58 ms 205.171.30.10' # . "\n" . # '10 56 ms 45 ms 43 ms 205.171.30.14' # . "\n" . # '11 46 ms 51 ms 41 ms hspr.new-york.ny.ne.us.psi.net [38.7.135.1]' # . "\n" . # '12 * 56 ms 52 ms se2.isc.us.psi.net [38.1.10.5]' # . "\n" . # '13 55 ms 56 ms * rc5.se.us.psi.net [38.1.25.197]' # . "\n" . # #'14 ip45.ci1.herndon.va.us.psi.net [38.146.148.45] reports: Destination net unreachable.' # '14 38.146.148.45 reports: Destination net unreachable.' # . "\n" . # '' # . "\n" . # 'Trace complete.' # . "\n" . # ''; # # Each table row returned by this function has the following columns: # ttl, packetNum, intermediatHostName, intermediateHostIp, time, status; sub parsePrintLine { my ($line, $tblRef, $successCnt, $ttl, $packetNum, $hostNameOld, $hostIpOld) = @_; my $time; my $hostName; my $hostIp; my $rest; my $cmpStr1 = ' '; my $cmpStr2 = ' '; my $cmpStr3 = ' '; my $status = ``; if (($osVer eq "B.11.00") || ($osType eq "AIX")) { $cmpStr1 = '^\s*(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)\s+(\d+)\s+ms\s*'; $cmpStr2 = '^\s*\d+\s+ms\s*'; $cmpStr3 = '^\s*(\*)\s*'; } elsif ($osType eq "WIN") { # In windows you can't specify the num of packets and the output looks like: # 1 <10 ms <10 ms <10 ms localhost-swi-52.example.com [127.0.1.1] # 2 78 ms 78 ms 78 ms localhost-swi-.example.com [127.0.1.1] # Also I couldn't find any doc statying that multple hosts might be shown, # so apparently only one host and it's IP are shown when there are alternate # routes. The following line captures all components as: # ttl time1 time2 time3 rest my $tmFailExp = '(?:(?:\<*(\d+)\s+ms)|\*)'; #m/^\s*(\d+)\s+${tmFailExp}\s+${tmFailExp}\s+${tmFailExp}\s+(.*)/o) $cmpStr1 = '^\s*(\d+)\s+' . $tmFailExp . '\s+' . $tmFailExp . '\s+' . $tmFailExp . '\s+(.*)'; # The following captures the host and ip $cmpStr2 = '\s*(\S+)\s+\[(\d+\.\d+\.\d+.\d+)\].*'; $cmpStr3 = '\s*(\d+)(?:\s.*)?\s(\S+)\s+\[(\d+\.\d+\.\d+\.\d+)\]\s+(.+)'; my $cmpStr4 = '\s*(\d+)\s+(\d+\.\d+\.\d+\.\d+)\s+(.+)'; my @tm_arr = (); unless(($ttl, $tm_arr[0], $tm_arr[1], $tm_arr[2], $rest) = $line =~ m/$cmpStr1/o) { trace("Failed 1st comparison.\n"); # Look for: # 15 ip45.ci1.net [38.146.148.45] reports: Destination net unreachable. my $msg; unless(($ttl, $hostName, $hostIp, $msg) = $line =~ m/$cmpStr3/o) { unless(($ttl, $hostIp, $msg) = $line =~ m/$cmpStr4/o) { trace "Failed parsing line."; trace "Line: [$line]\n"; print "em_error=Failed parsing line."; exit 1; } $hostName = ''; } $tblRef->[@$tblRef] = [$ttl, 0, "$hostName", "$hostIp", '', "$msg"]; trace("$ttl|0|$hostName|$hostIp||$msg\n"); return; } trace("Succeeded 1st comparison, rest is '$rest'.\n"); my $i; for ($i = 0; $i < 3; $i++) { if($tm_arr[$i] eq '') { $tblRef->[@$tblRef] = [$ttl, "$i", '', '', '', "$noResponseStr"]; } else { if(! defined($hostName)) { # $cmpStr2 = "\s*(\S+)\s+\[(\d+\.\d+\.\d+.\d+)\].*"; unless(($hostName, $hostIp) = $rest =~ m/\s*(\S+)\s+\[(\d+\.\d+\.\d+.\d+)\].*/o) { unless(($hostIp) = $rest =~ m/\s*(\d+\.\d+\.\d+.\d+).*/o) { trace "Failed parsing line."; trace "Line: [$line]\n"; print "em_error=Failed parsing line."; exit 1; } $hostName = ''; } trace("Succeeded 2nd comparison, rest is '$rest'.\n"); #sometimes windows does not resolve the host name for the last node if($hostName eq '') { #since the trace was successful, just set the hostName to target. $hostName = $target; } } $tblRef->[@$tblRef] = [$ttl, "$i", "$hostName", "$hostIp", "$tm_arr[$i]", "$successStr"]; } } return; } else { if ($osType eq "OSF1") { $cmpStr1 = '^\s*(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)\s+(\d+\.?\d*)\s+ms\s*(.*)'; $cmpStr2 = '^\s*(\d+\.?\d*)\s+ms\s*(.*)'; $cmpStr3 = '^\s*(\*)\s*(.*)'; } else { # hostN ____IP__Address___ __time__ rest $cmpStr1 = '^\s*(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)\s+(\d+\.\d+)\s+ms\s*(.*)'; $cmpStr2 = '^\s*(\d+\.\d+)\s+ms\s*(.*)'; $cmpStr3 = '^\s*(\*)\s*(.*)'; } } if(((! defined($line)) || ($line eq '')) && (defined($ttl))) { return ''; } trace("Line to parse is: $line\n"); if(! defined($$successCnt)) { $$successCnt = 0; } if(! defined($ttl)) { unless(($ttl, $rest) = $line =~ m/^\s*(\d+)\s+(.*)/o) { trace "Line: [$line]\n"; print "em_error=Failed parsing line."; exit 1; } $line = $rest; trace("line: $line\n"); $packetNum = 0; } unless(($hostName, $hostIp, $time, $rest) = $line =~ m/$cmpStr1/o) { trace("Failed 1st comparison.\n"); unless(($time, $rest) = $line =~ m/$cmpStr2/o) { trace("Failed 2nd comparison.\n"); unless(($time, $rest) = $line =~ m/$cmpStr3/o) { trace "Line: [$line]\n"; print "em_error=Failed parsing line."; exit 1; } $tblRef->[@$tblRef] = [$ttl, $packetNum, '', '', '', "$noResponseStr"]; trace("$ttl|$packetNum||||-\n"); parsePrintLine($rest, $tblRef, $successCnt, $ttl, ++$packetNum, $hostNameOld, $hostIpOld); return; } trace("Succeeded 2nd comparison.\n"); $hostName = $hostNameOld; $hostIp = $hostIpOld; } trace("Succeeded 1st comparison, rest is '$rest'.\n"); my $oldRest = $rest; unless(($status, $rest) = $oldRest =~ m/^\s*(!\S*)((\s.*)|($))/o) { # No error code trace("Not !*\n"); $rest = $oldRest; $status = "$successStr"; # NLS? What's that? ($$successCnt)++; } else # Found error code, now "transalate" it { my $ICMPCode; if($status eq "!H") { $status = "Host unreachable"; } elsif($status eq "!N") { $status = "Network unreachable"; } elsif($status eq "!P") { $status = "Protocol unreachable"; } elsif($status eq "!S") { $status = "Source route failed"; } elsif($status eq "!F") { $status = "Fragmentation needed"; } elsif($status eq "!X") { $status = "Communication administratively prohibited"; } elsif(($ICMPCode) = $status =~ m/!(\d+)/o) { $status = "ICMP unreachable code $ICMPCode."; } else { trace("Unknown status found! [$status]\n"); } } $tblRef->[@$tblRef] = [$ttl, $packetNum, $hostName, $hostIp, $time, $status]; trace("$ttl|$packetNum|$hostName|$hostIp|$time|$status\n"); trace("rest: $rest\n"); trace("success counter: $$successCnt\n"); parsePrintLine($rest, $tblRef, $successCnt, $ttl, ++$packetNum, $hostName, $hostIp); return; } ############################################################################### ############################################################################### __END__ sub doPingVerbose { my () = @_; my $r; if ($osType eq "SOL") { # EMD_TRACE("Getting OS response for Sun OS.\n"); $ENV{PATH} = "/usr/bin:/usr/sbin:/usr/local/bin:/local/bin"; if(!($r = `ping -s -t $maxTtl $target 64 $numPackets`)) { #EMD_DEBUG("Failed to execute ping: $!", "$target"); print "em_error=Failed to ping host"; exit 1; } } elsif ($osType eq "LNX") { # EMD_TRACE("Getting OS response for Linux OS.\n"); if(!($r = `/bin/ping $target -s 64 -c $numPackets -t $maxTtl`)) { #EMD_DEBUG("Failed to execute ping: $!", "$target"); print "em_error=Failed to ping host"; exit 1; } } else { # EMD_TRACE("Getting OS response for HP OS.\n"); $ENV{PATH} = "/usr/bin:/usr/sbin"; if(!($r = `ping -t $maxTtl $target 64 $numPackets`)) { # EMD_DEBUG("Failed to execute ping: $!", "$target"); print "em_error=Failed to ping host"; exit 1; } } my @resLns = split(m/\n/o, $r); my $pingRegExp = '\d+\s+bytes\s+from\s+(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)' . ':\s+icmp_seq=(\d+)\.\s+time=\(d+)\.\s+ms'; my $pingFailRegExp = 'ICMP\s+Time\s+exceeded\s+in\s+transit\s+from\s+(\S+)' . '\s+\((\d+\.\d+\.\d+\.\d+)\)'; my $i; for($i = 0; $i < @resLns; $i++) { my ($host, $ip, $icmpSeq, $time); my $status = -1; if(($host, $ip, $icmpSeq, $time) = $resLns[$i] =~ m/$pingRegExp/o) { $status = 1; } else { if((($host, $ip) = $resLns[$i++] =~ m/$pingFailReqExp/o) && ($resLns[$i] =~ m/$pingFailLine2/o)) { $status = 0; $icmpSeq = ''; $time = ''; } } if($status >= 0) { print("$lineHeader" . "delimiter" . "$host" . "delimiter" . "$ip" . "delimiter" . "$icmpSeq" . "delimiter" . "$time" . "delimiter" . "$status"); } } # make sure we got two lines back if(@resLns < 2) { print "em_error=Failed spliting lines from result set"; exit 1; } my @res = split(m/=/o, $resLns[1]); }