1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-29 19:09:01 +00:00

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.
This commit is contained in:
david
2010-03-23 23:30:36 +00:00
parent cb22a8a788
commit 2684b78ce5
2 changed files with 83 additions and 62 deletions

View File

@@ -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.

View File

@@ -1384,68 +1384,6 @@ double TracerouteState::completion_fraction() const {
return sum / hosts.size();
}
static int traceroute_direct(std::vector<Target *> targets);
int traceroute(std::vector<Target *> &Targets) {
std::vector<Target *>::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<Target *> targets) {
return 1;
}
static int traceroute_remote(std::vector<Target *> targets) {
std::vector<Target *>::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<Target *> &Targets) {
std::vector<Target *> direct, remote;
std::vector<Target *>::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;