{% from "partials/_macros.html" import card_header, verdict_pill %} {# Network neighborhood & topology — DNS resolvers, ARP (IPv4) and NDP (IPv6) neighbor caches, and the routing table. The DNS-hijack / ARP-spoof / route-redirection surfaces. Tables are small and bounded, so all rows show behind one shared verdict + search filter (no pagination). #} {# ----- reusable section renderer: header + counts + table (defined before use — Jinja2 does not hoist macros) ----- #} {% macro _topo_section(title, subtitle, rows, counts, columns) %}
{{ title }} {{ subtitle }}
{{ counts.total }} rows {% if counts.malicious %} {{ counts.malicious }} malicious {% endif %} {% if counts.suspicious %} {{ counts.suspicious }} suspicious {% endif %}
{% if rows %}
{% for label, _ in columns %} {% endfor %} {% for r in rows %} {% for _, key in columns %} {% endfor %} {% endfor %}
verdict{{ label }}why
{% if r.verdict %}{{ verdict_pill(r.verdict) }} {% else %}{% endif %} {{ r[key] or "—" }}{{ r.reasoning }}
{% else %}
none
{% endif %}
{% endmacro %}
{{ card_header("Network topology — resolvers, neighbors & routes") }} {% if topo %} {# ----- shared filter bar ----- #}
{% endif %} {% if topo and topo.any %} {% set c = topo.counts %} {# ===== DNS resolvers ===== #} {{ _topo_section( "DNS resolvers", "nameservers this host is configured to use", topo.resolvers, c.resolvers, [("resolver", "server"), ("scope", "scope"), ("search domains", "search"), ("interface", "interface")] ) }} {# ===== Routing table ===== #} {{ _topo_section( "Routes", "where traffic is sent — watch the default route", topo.routes, c.routes, [("destination", "destination"), ("gateway", "gateway"), ("interface", "interface"), ("flags", "flags")] ) }} {# ===== ARP (IPv4 neighbors) ===== #} {{ _topo_section( "ARP table (IPv4 neighbors)", "ip ↔ mac — a new mac for the gateway is ARP-spoof", topo.arp, c.arp, [("ip", "ip"), ("mac", "mac"), ("interface", "interface"), ("flags", "flags")] ) }} {# ===== NDP (IPv6 neighbors) ===== #} {{ _topo_section( "NDP neighbors (IPv6)", "the IPv6 analog of ARP", topo.ndp, c.ndp, [("ip", "ip"), ("mac", "mac"), ("interface", "interface"), ("state", "state")] ) }} {% elif topo %}
no topology rows match the current filters.
{% else %}
no topology data captured yet — wait for a collection cycle to complete.
{% endif %}