Features to implement next, ordered by priority.
Effort: Low — data already collected, no new capture needed
Files: lib/ndp_stats.go, lib/display.go
MLD membership data in PeerStats.Groups already fingerprints OS:
| Groups Present | Likely OS / Device |
|---|---|
ff02::fb only |
macOS or Linux (Avahi) |
ff02::1:3 present |
Windows |
ff02::fb + ff02::1:3 |
Windows with mDNS |
ff02::c (SSDP) |
IoT / smart home device |
ff02::2 (All Routers) |
Acting as router |
Implementation:
- Add
GuessedOS stringtoPeerSummary - Add
GuessOS(groups []string) stringfunction inndp_stats.gothat scores group memberships - Show as a
Typecolumn (truncated) in the peers table - Show full value in peer detail view
Effort: Low — MACs already extracted, just need a lookup table
Files: lib/oui.go (new), lib/ndp_stats.go, lib/display.go
Map the first 3 bytes of a MAC to a manufacturer name.
Implementation:
- Create
lib/oui.gowith aLookupVendor(mac string) stringfunction - Hardcode a map of the top ~150 vendors by network market share (Apple, Raspberry Pi Foundation, Intel, Cisco, TP-Link, Netgear, Ubiquiti, Amazon, Google, Samsung, etc.) — keeps the binary small
- Add
Vendor stringtoPeerSummary, populate inGetStats() - Show in peer detail view; optionally add a narrow truncated column to the peers table
Effort: Medium — requires a new listener goroutine
Files: lib/mdns_listener.go (new), lib/ndp_stats.go, lib/display.go, main.go
Listen on ff02::fb UDP port 5353, parse DNS responses, attach hostnames to peers.
Implementation:
- New
MDNSListenerstruct with aRun(ctx context.Context)method, same pattern asNDPListener - Join multicast group
ff02::fbon the target interface - Parse AAAA and PTR records using
golang.org/x/net/dns/dnsmessage(already in module graph viax/net) - Add
Hostname stringtoPeerStatsandPeerSummary; populate via newRecordHostname(ip, hostname string)onNDPStats - Show hostname column in peers table (truncated); full value in detail view
- Start listener in
main.goalongsideNDPListener
Effort: Low — existing data structures, just marshal and write
Files: lib/export.go (new), main.go
Periodic JSON snapshots for integration with other tools.
Implementation:
- Add
--output <path>and--output-interval <duration>(default:30s) flags tomain.go - New
lib/export.gowithWriteSnapshot(stats *NDPStats, path string) error - Output structure mirrors existing
PeerSummaryandRouterInfotypes — addjsontags - Run a ticker goroutine in
main.gothat callsWriteSnapshotwhen--outputis set - Write atomically: write to
<path>.tmpthenos.Renameto avoid partial reads
Effort: Medium — requires state comparison on each update
Files: lib/security.go (new), lib/ndp_stats.go, main.go
Detect and log anomalous NDP behavior to the log file.
Alerts to implement (v1):
- New router seen for the first time
- Known router's MAC address changed
- Known peer's MAC address changed (possible spoofing)
- Router advertising a prefix not seen before
Implementation:
SecurityMonitorstruct wraps*NDPStatsand holds a*slog.Logger- Expose
CheckRouter(new RouterInfo)andCheckPeer(ip, mac string)methods - Call these from
NDPListener.Run()afterRecordRouter/RecordMAC - Log at
WARNlevel with structured fields for easy grep/SIEM ingestion - No TUI changes needed for v1 — log file output is sufficient
- OS fingerprinting (zero infra, immediate TUI improvement)
- OUI vendor lookup (same — quick win on top of existing MAC data)
- JSON export (enables tool to integrate into larger workflows)
- mDNS listener (biggest UX win — human names for addresses)
- Security event logging (foundational for monitoring use cases)