diff --git a/zenmap/radialnet/util/integration.py b/zenmap/radialnet/util/integration.py index ed54475f6..26ff6c83c 100644 --- a/zenmap/radialnet/util/integration.py +++ b/zenmap/radialnet/util/integration.py @@ -176,11 +176,21 @@ class TracerouteHostInfo(object): hostnames = property(lambda self: self.hostname and [self.hostname] or []) +def find_hop_by_ttl(hops, ttl): + assert ttl >= 0, "ttl must be non-negative" + if ttl == 0: # Same machine (i.e. localhost) + return {"ipaddr": "127.0.0.1/8"} + for h in hops: + if ttl == int(h["ttl"]): + return h + return None + def make_graph_from_hosts(hosts): #hosts = parser.get_root().search_children('host', deep=True) graph = Graph() nodes = list() node_cache = {} + invalid_node_cache = {} # Setting initial reference host main_node = NetNode() @@ -210,13 +220,7 @@ def make_graph_from_hosts(hosts): # Getting nodes of host by ttl for ttl in range(1, max(ttls) + 1): if ttl in ttls: - # Find a hop by ttl - hop = None - for h in hops: - if ttl == int(h["ttl"]): - hop = h - break - + hop = find_hop_by_ttl(hops, ttl) node = node_cache.get(hop["ipaddr"]) if node is None: node = NetNode() @@ -245,14 +249,34 @@ def make_graph_from_hosts(hosts): else: graph.set_connection(node, prev_node) else: - node = NetNode() - nodes.append(node) + # Add an "anonymous" node only if there isn't already a node + # equivalent to it (i.e. at same distance from the previous + # "real" node) - node.set_draw_info({"valid": False}) - node.set_draw_info( - {"color": (1, 1, 1), "radius": NONE_RADIUS}) + pre_hop = None + pre_hop_distance = 0 + for i in range(1, ttl + 1): + pre_hop = find_hop_by_ttl(hops, ttl-i) + if pre_hop is not None: + pre_hop_distance = i + break - graph.set_connection(node, prev_node) + assert pre_hop is not None, "pre_hop should have become localhost if nothing else" + + key = (pre_hop["ipaddr"], pre_hop_distance) + + if key not in invalid_node_cache: + node = NetNode() + nodes.append(node) + + node.set_draw_info({"valid":False}) + node.set_draw_info({"color":(1,1,1), "radius":NONE_RADIUS}) + + graph.set_connection(node, prev_node) + + invalid_node_cache[key] = node + + node = invalid_node_cache[key] prev_node = node endpoints[host] = node