feat: MAC lookup in scan FDB (API mac-locations, UI table, index)

Made-with: Cursor
This commit is contained in:
PTah
2026-04-13 12:41:48 +10:00
parent 886300b6c0
commit d85ec9ff61
9 changed files with 332 additions and 41 deletions
+43
View File
@@ -71,6 +71,8 @@ type Store interface {
ListInterfaceResults(scanID string, filterIP string, limit int) []InterfaceResult
SavePortDeviceResult(scanID string, result PortDeviceResult) error
ListPortDeviceResults(scanID string, filterIP string, filterIfIndex int, limit int) []PortDeviceResult
// ListPortDevicesByMac — строки FDB по точному MAC (mac уже в каноническом виде, см. NormalizeMAC).
ListPortDevicesByMac(scanID string, mac string, limit int) []PortDeviceResult
// PurgeAllScanData удаляет все сканы и связанные строки (хосты, порты, SNMP, LLDP, интерфейсы).
PurgeAllScanData() error
}
@@ -439,6 +441,47 @@ func (s *MemoryStore) ListPortDeviceResults(scanID string, filterIP string, filt
return out
}
func (s *MemoryStore) ListPortDevicesByMac(scanID string, mac string, limit int) []PortDeviceResult {
if limit <= 0 {
limit = 5000
}
if mac == "" {
return nil
}
s.mu.RLock()
defer s.mu.RUnlock()
items := s.fdb[scanID]
filtered := make([]PortDeviceResult, 0, 8)
for _, r := range items {
if NormalizeMAC(r.MAC) == mac {
filtered = append(filtered, r)
}
}
sort.Slice(filtered, func(i, j int) bool {
if filtered[i].IP != filtered[j].IP {
return filtered[i].IP < filtered[j].IP
}
if filtered[i].IfIndex != filtered[j].IfIndex {
return filtered[i].IfIndex < filtered[j].IfIndex
}
if filtered[i].Vlan != filtered[j].Vlan {
return filtered[i].Vlan < filtered[j].Vlan
}
if filtered[i].MAC != filtered[j].MAC {
return filtered[i].MAC < filtered[j].MAC
}
return filtered[i].LearnedIP < filtered[j].LearnedIP
})
if len(filtered) <= limit {
out := make([]PortDeviceResult, len(filtered))
copy(out, filtered)
return out
}
out := make([]PortDeviceResult, limit)
copy(out, filtered[:limit])
return out
}
func applyDefaultOptions(opts *ScanOptions) {
if opts.PingTimeoutMS <= 0 {
opts.PingTimeoutMS = 700