From 2684b78ce56e517c1c2e1186e3dc44d762477b62 Mon Sep 17 00:00:00 2001 From: david Date: Tue, 23 Mar 2010 23:30:36 +0000 Subject: [PATCH] In traceroute, separate the directly connected targets from the rest before starting. There is a special function that does a trace of directly connected targets without sending any packets, just by filling in one hop directly to the target. The traceroute code was only checking whether the first target in the group was directly connected, and if it was, it assumed all of them were. Now it filters the list into two and calls traceroute_direct on one and traceroute_remote on the other. Fyodor discovered this problem today. --- CHANGELOG | 5 ++ traceroute.cc | 140 ++++++++++++++++++++++++++++---------------------- 2 files changed, 83 insertions(+), 62 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ca2b7be2b..487f2f15b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,11 @@ [NOT YET RELEASED] +o Fixed a bug in traceroute that could happen when directly connected + and routed targets were in the same hostgroup. If the first target + was directly connected, the traceroute for all targets in the group + would have a trace of one hop. + o [NSE] Added the qscan script to repeatedly probe ports on a host to gather round-trip times for each port. The script then uses these times to group together ports with statistically equivalent RTTs. diff --git a/traceroute.cc b/traceroute.cc index 787414ccb..4b122fbdc 100644 --- a/traceroute.cc +++ b/traceroute.cc @@ -1384,68 +1384,6 @@ double TracerouteState::completion_fraction() const { return sum / hosts.size(); } -static int traceroute_direct(std::vector targets); - -int traceroute(std::vector &Targets) { - std::vector::iterator target_iter; - - if (Targets.empty() || Targets[0]->ifType() == devt_loopback) - return 1; - - if (Targets[0]->directlyConnected()) - /* Special case for directly connected targets. */ - return traceroute_direct(Targets); - - TracerouteState global_state(Targets); - - global_id = get_random_u16(); - - ScanProgressMeter SPM("Traceroute"); - - o.current_scantype = TRACEROUTE; - - while (!global_state.active_hosts.empty()) { - struct timeval now; - long int timeout; - - global_state.send_new_probes(); - now = get_now(); - timeout = TIMEVAL_SUBTRACT(global_state.next_send_time, now); - global_state.read_replies(timeout); - global_state.cull_timeouts(); - global_state.remove_finished_hosts(); - - if (keyWasPressed()) - SPM.printStats(global_state.completion_fraction(), NULL); - } - - SPM.endTask(NULL, NULL); - - if (!o.noresolve) - global_state.resolve_hops(); - /* This puts the hops into the Targets known by the global_state. */ - global_state.transfer_hops(); - - /* Update initial_ttl to be the highest distance seen in this host group, as - an estimate for the next. */ - initial_ttl = 0; - for (target_iter = Targets.begin(); - target_iter != Targets.end(); - target_iter++) { - initial_ttl = MAX(initial_ttl, (*target_iter)->traceroute_hops.size()); - } - - if (hop_cache_size() > MAX_HOP_CACHE_SIZE) { - if (o.debugging) { - log_write(LOG_STDOUT, "Clearing hop cache that has grown to %d\n", - hop_cache_size()); - } - traceroute_hop_cache_clear(); - } - - return 1; -} - /* This is a special case of traceroute when all the targets are directly connected. Because the distance to each target is known to be 1, we send no probes at all, only fill in a TracerouteHop structure. */ @@ -1472,6 +1410,84 @@ static int traceroute_direct(std::vector targets) { return 1; } +static int traceroute_remote(std::vector targets) { + std::vector::iterator target_iter; + + if (targets.empty()) + return 1; + + TracerouteState global_state(targets); + + global_id = get_random_u16(); + + ScanProgressMeter SPM("Traceroute"); + + o.current_scantype = TRACEROUTE; + + while (!global_state.active_hosts.empty()) { + struct timeval now; + long int timeout; + + global_state.send_new_probes(); + now = get_now(); + timeout = TIMEVAL_SUBTRACT(global_state.next_send_time, now); + global_state.read_replies(timeout); + global_state.cull_timeouts(); + global_state.remove_finished_hosts(); + + if (keyWasPressed()) + SPM.printStats(global_state.completion_fraction(), NULL); + } + + SPM.endTask(NULL, NULL); + + if (!o.noresolve) + global_state.resolve_hops(); + /* This puts the hops into the targets known by the global_state. */ + global_state.transfer_hops(); + + /* Update initial_ttl to be the highest distance seen in this host group, as + an estimate for the next. */ + initial_ttl = 0; + for (target_iter = targets.begin(); + target_iter != targets.end(); + target_iter++) { + initial_ttl = MAX(initial_ttl, (*target_iter)->traceroute_hops.size()); + } + + if (hop_cache_size() > MAX_HOP_CACHE_SIZE) { + if (o.debugging) { + log_write(LOG_STDOUT, "Clearing hop cache that has grown to %d\n", + hop_cache_size()); + } + traceroute_hop_cache_clear(); + } + + return 1; +} + +int traceroute(std::vector &Targets) { + std::vector direct, remote; + std::vector::iterator target_iter; + + /* Separate directly connected targets from remote targets. */ + for (target_iter = Targets.begin(); + target_iter != Targets.end(); + target_iter++) { + if ((*target_iter)->ifType() == devt_loopback) + ; /* Ignore */ + else if ((*target_iter)->directlyConnected()) + direct.push_back(*target_iter); + else + remote.push_back(*target_iter); + } + + traceroute_direct(direct); + traceroute_remote(remote); + + return 1; +} + static struct timeval get_now(struct timeval *now) { struct timeval tv;