def world_trace(self):
        """Display traceroute results on a world map."""

        # Check that the geoip2 module can be imported
        # Doc: http://geoip2.readthedocs.io/en/latest/
        try:
            # GeoIP2 modules need to be imported as below
            import geoip2.database
            import geoip2.errors
        except ImportError:
            warning("Cannot import geoip2. Won't be able to plot the world.")
            return []
        # Check availability of database
        if not conf.geoip_city:
            warning("Cannot import the geolite2 CITY database.\n"
                    "Download it from http://dev.maxmind.com/geoip/geoip2/geolite2/"  # noqa: E501
                    " then set its path to conf.geoip_city")
            return []
        # Check availability of plotting devices
        try:
            import cartopy.crs as ccrs
        except ImportError:
            warning("Cannot import cartopy.\n"
                    "More infos on http://scitools.org.uk/cartopy/docs/latest/installing.html")  # noqa: E501
            return []
        if not MATPLOTLIB:
            warning("Matplotlib is not installed. Won't be able to plot the world.")  # noqa: E501
            return []

        # Open & read the GeoListIP2 database
        try:
            db = geoip2.database.Reader(conf.geoip_city)
        except Exception:
            warning("Cannot open geoip2 database at %s", conf.geoip_city)
            return []

        # Regroup results per trace
        ips = {}
        rt = {}
        ports_done = {}
        for s, r in self.res:
            ips[r.src] = None
            if s.haslayer(TCP) or s.haslayer(UDP):
                trace_id = (s.src, s.dst, s.proto, s.dport)
            elif s.haslayer(ICMP):
                trace_id = (s.src, s.dst, s.proto, s.type)
            else:
                trace_id = (s.src, s.dst, s.proto, 0)
            trace = rt.get(trace_id, {})
            if not r.haslayer(ICMP) or r.type != 11:
                if trace_id in ports_done:
                    continue
                ports_done[trace_id] = None
            trace[s.ttl] = r.src
            rt[trace_id] = trace

        # Get the addresses locations
        trt = {}
        for trace_id in rt:
            trace = rt[trace_id]
            loctrace = []
            for i in range(max(trace)):
                ip = trace.get(i, None)
                if ip is None:
                    continue
                # Fetch database
                try:
                    sresult = db.city(ip)
                except geoip2.errors.AddressNotFoundError:
                    continue
                loctrace.append((sresult.location.longitude, sresult.location.latitude))  # noqa: E501
            if loctrace:
                trt[trace_id] = loctrace

        # Load the map renderer
        plt.figure(num='Scapy')
        ax = plt.axes(projection=ccrs.PlateCarree())
        # Draw countries
        ax.coastlines()
        ax.stock_img()
        # Set normal size
        ax.set_global()
        # Add title
        plt.title("Scapy traceroute results")

        from matplotlib.collections import LineCollection
        from matplotlib import colors as mcolors
        colors_cycle = iter(mcolors.BASE_COLORS)
        lines = []

        # Split traceroute measurement
        for key, trc in six.iteritems(trt):
            # Get next color
            color = next(colors_cycle)
            # Gather mesurments data
            data_lines = [(trc[i], trc[i + 1]) for i in range(len(trc) - 1)]
            # Create line collection
            line_col = LineCollection(data_lines, linewidths=2,
                                      label=key[1],
                                      color=color)
            lines.append(line_col)
            ax.add_collection(line_col)
            # Create map points
            lines.extend([ax.plot(*x, marker='.', color=color) for x in trc])

        # Generate legend
        ax.legend()

        # Call show() if matplotlib is not inlined
        if not MATPLOTLIB_INLINED:
            plt.show()

        # Clean
        ax.remove()

        # Return the drawn lines
        return lines
def world_trace ( self ) : try : import geoip2 . database import geoip2 . errors except ImportError : warning ( "Cannot import geoip2. Won't be able to plot the world." ) return [ ] if not conf . geoip_city : warning ( "Cannot import the geolite2 CITY database.\n" "Download it from http://dev.maxmind.com/geoip/geoip2/geolite2/" " then set its path to conf.geoip_city" ) return [ ] try : import cartopy . crs as ccrs except ImportError : warning ( "Cannot import cartopy.\n" "More infos on http://scitools.org.uk/cartopy/docs/latest/installing.html" ) return [ ] if not MATPLOTLIB : warning ( "Matplotlib is not installed. Won't be able to plot the world." ) return [ ] try : db = geoip2 . database . Reader ( conf . geoip_city ) except Exception : warning ( "Cannot open geoip2 database at %s" , conf . geoip_city ) return [ ] ips = { } rt = { } ports_done = { } for s , r in self . res : ips [ r . src ] = None if s . haslayer ( TCP ) or s . haslayer ( UDP ) : trace_id = ( s . src , s . dst , s . proto , s . dport ) elif s . haslayer ( ICMP ) : trace_id = ( s . src , s . dst , s . proto , s . type ) else : trace_id = ( s . src , s . dst , s . proto , 0 ) trace = rt . get ( trace_id , { } ) if not r . haslayer ( ICMP ) or r . type != 11 : if trace_id in ports_done : continue ports_done [ trace_id ] = None trace [ s . ttl ] = r . src rt [ trace_id ] = trace trt = { } for trace_id in rt : trace = rt [ trace_id ] loctrace = [ ] for i in range ( max ( trace ) ) : ip = trace . get ( i , None ) if ip is None : continue try : sresult = db . city ( ip ) except geoip2 . errors . AddressNotFoundError : continue loctrace . append ( ( sresult . location . longitude , sresult . location . latitude ) ) if loctrace : trt [ trace_id ] = loctrace plt . figure ( num = 'Scapy' ) ax = plt . axes ( projection = ccrs . PlateCarree ( ) ) ax . coastlines ( ) ax . stock_img ( ) ax . set_global ( ) plt . title ( "Scapy traceroute results" ) from matplotlib . collections import LineCollection from matplotlib import colors as mcolors colors_cycle = iter ( mcolors . BASE_COLORS ) lines = [ ] for key , trc in six . iteritems ( trt ) : color = next ( colors_cycle ) data_lines = [ ( trc [ i ] , trc [ i + 1 ] ) for i in range ( len ( trc ) - 1 ) ] line_col = LineCollection ( data_lines , linewidths = 2 , label = key [ 1 ] , color = color ) lines . append ( line_col ) ax . add_collection ( line_col ) lines . extend ( [ ax . plot ( * x , marker = '.' , color = color ) for x in trc ] ) ax . legend ( ) if not MATPLOTLIB_INLINED : plt . show ( ) ax . remove ( ) return lines
Display traceroute results on a world map.