Class: Scriptroute::Rockettrace
- Inherits:
-
Object
- Object
- Scriptroute::Rockettrace
- Includes:
- Enumerable
- Defined in:
- lib/scriptroute/rockettrace.rb
Overview
This is what traceroute would do, if only we could change it for the specific purpose of network mapping.
Instance Attribute Summary collapse
-
#destination_address ⇒ Object
readonly
A value representing the address probed (perhaps if given a hostname).
-
#finished_because ⇒ String
readonly
An explanation of why the trace terminated.
Instance Method Summary collapse
-
#[](ttl) ⇒ Array<IPaddress,rtt,response>
The results of all probes at a particular TTL.
-
#each ⇒ Object
Invokes the given block for each ttl and result array, as described in #[].
-
#initialize(destination, startTTL = 1, use_tcp = false, repetitions = 3, stopTTL = 64, reprieves = 1) ⇒ Rockettrace
constructor
Creates a Rockettrace object, which wraps the results of the trace.
-
#length ⇒ Fixnum
The last TTL for which results are present (even if unresponsive).
-
#responsive_length ⇒ Fixnum
The maximum responsive ttl detected.
- #to_s(nameify = nil) ⇒ String
Constructor Details
#initialize(destination, startTTL = 1, use_tcp = false, repetitions = 3, stopTTL = 64, reprieves = 1) ⇒ Rockettrace
Creates a Rockettrace object, which wraps the results of the trace.
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/scriptroute/rockettrace.rb', line 29 def initialize(destination, startTTL=1, use_tcp=false, repetitions=3, stopTTL=64, reprieves=1) # construct the first probe packet. probe = use_tcp ? Scriptroute::TCP.new(0) : Scriptroute::UDP.new(12) # 12 bytes of udp data are needed to ensure a response probe.ip_dst = destination # causes the interpreter to lookup the destination if not an ip address already. @destination_address = probe.ip_dst @results = Hash.new { |h,k| h[k] = Array.new } @finished_because = "last ttl" @reprieves = reprieves # one more than the number of timeout responses to be tolerated. @last_ttl = 0 catch :done do ( startTTL..stopTTL ).each { |ttl| probe.ip_ttl = ttl packets = Scriptroute::send_train([ Struct::DelayedPacket.new(0,probe) ]) if(packets[0].response) then if(packets[0].response.packet.is_a?(Scriptroute::ICMP)) then if(@results.keys.detect { |e| # puts "#{@results[e][0][0]} ==? #{packets[0].response.packet.ip_src}"; @results[e][0][0] == packets[0].response.packet.ip_src }) then # we've found a loop. # append the loopy entry to the path # puts "loop detected" @results[ttl].push [ packets[0].response.packet.ip_src, packets[0].rtt, '' ] # and we're done. @last_ttl = ttl @finished_because = "loop" throw :done else # no loop. we might continue. @results[ttl].push [ packets[0].response.packet.ip_src, packets[0].rtt, '' ] # any unreach message is sufficient to stop us. if(packets[0].response.packet.icmp_type == Scriptroute::ICMP::ICMP_UNREACH) then if(packets[0].response.packet.icmp_code != Scriptroute::ICMP::ICMP_UNREACH_PORT) then @results[ttl][-1][2] = "code%d" % packets[0].response.packet.icmp_code @finished_because = "unreachable" else @finished_because = "done" end @last_ttl = ttl throw :done end end else # got a response, but not icmp. let's just assume for now # that we're running a tcp traceroute and got the tcp reset. @last_ttl = ttl @finished_because = "app" throw :done end # end received response block. else # got no response here. @results[ttl].push [ '', "*", '' ] # we want two consecutive unresponsive hops before we decide it's over. if @last_ttl == 0 @last_ttl = ttl + @reprieves elsif @last_ttl < ttl # a prior reprieve was taken. @last_ttl = ttl + @reprieves end # if reprieves is zero, fall through and finish. if(@last_ttl == ttl) then @finished_because = "unresponsive" throw :done end end } end # make certain that last_ttl is set, even if we hit the end early. if(@last_ttl == 0) then @last_ttl = stopTTL end ( 2..repetitions ).each { |rep| packets = Scriptroute::send_train((startTTL..@last_ttl).map { |ttl| nprobe = use_tcp ? Scriptroute::TCP.new(0) : Scriptroute::UDP.new(12) nprobe.ip_dst = probe.ip_dst # avoid the name lookup nprobe.ip_ttl = ttl Struct::DelayedPacket.new(0.1, nprobe) }) packets.each { |four| # four.response may be nil (?) # four.probe.packet may be nil if the packet was not seen outgoing. if(four.response && four.probe.packet) then @results[four.probe.packet.ip_ttl].push [ four.response.packet.ip_src, four.rtt, '' ] else @results[four.probe.packet.ip_ttl].push [ '', "*", '' ] end } } end |
Instance Attribute Details
#destination_address ⇒ Object (readonly)
Returns a value representing the address probed (perhaps if given a hostname).
9 10 11 |
# File 'lib/scriptroute/rockettrace.rb', line 9 def destination_address @destination_address end |
#finished_because ⇒ String (readonly)
Returns an explanation of why the trace terminated.
8 9 10 |
# File 'lib/scriptroute/rockettrace.rb', line 8 def finished_because @finished_because end |
Instance Method Details
#[](ttl) ⇒ Array<IPaddress,rtt,response>
Returns the results of all probes at a particular TTL.
139 140 141 |
# File 'lib/scriptroute/rockettrace.rb', line 139 def [](ttl) @results[ttl][0][0] end |
#each ⇒ Object
Invokes the given block for each ttl and result array, as described in #[]
144 145 146 |
# File 'lib/scriptroute/rockettrace.rb', line 144 def each @results.each { |ttl,res| yield ttl, res } end |
#length ⇒ Fixnum
Returns the last TTL for which results are present (even if unresponsive).
128 129 130 |
# File 'lib/scriptroute/rockettrace.rb', line 128 def length return @last_ttl end |
#responsive_length ⇒ Fixnum
Returns the maximum responsive ttl detected.
133 134 135 |
# File 'lib/scriptroute/rockettrace.rb', line 133 def responsive_length l = ( 1.. @last_ttl ).to_a.reverse.detect { |ttl| @results[ttl][0][0] != '' } end |
#to_s(nameify = nil) ⇒ String
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/scriptroute/rockettrace.rb', line 152 def to_s(nameify=nil) nameify = lambda { |x| x } if (nameify == nil) @results.sort.map { |ttl,res| lastip = ''; ttl.to_s + " " + res.map { |ip,rtt,err| if(ip != lastip) then lastip = ip if ip != '' then nameify.call(ip).to_s + " " else "" end else "" end + if(rtt == '*') then '*' else "%5.3f ms" % (rtt * 1000.0) end + if(err != '') then " " + err else "" end }.join(' ') }.join("\n") end |