diff --git a/arp.go b/arp.go index f1a5d0c..9736c09 100644 --- a/arp.go +++ b/arp.go @@ -63,6 +63,11 @@ func (t *Tendrils) parseARPDarwin() []arpEntry { scanner := bufio.NewScanner(strings.NewReader(string(output))) for scanner.Scan() { line := scanner.Text() + + if strings.Contains(line, "permanent") { + continue + } + fields := strings.Fields(line) if len(fields) < 6 { continue diff --git a/nodes.go b/nodes.go index 7aaeed7..3c10a95 100644 --- a/nodes.go +++ b/nodes.go @@ -122,14 +122,16 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw node := n.nodes[targetID] var added []string - if node.LocalPort == "" && childPort != "" { - node.LocalPort = childPort - added = append(added, "localPort="+childPort) - } + if targetID != 0 { + if node.LocalPort == "" && childPort != "" { + node.LocalPort = childPort + added = append(added, "localPort="+childPort) + } - if node.ParentPort == "" && parentPort != "" { - node.ParentPort = parentPort - added = append(added, "parentPort="+parentPort) + if node.ParentPort == "" && parentPort != "" { + node.ParentPort = parentPort + added = append(added, "parentPort="+parentPort) + } } for _, ip := range ips { diff --git a/snmp.go b/snmp.go index d098cc1..6d5321a 100644 --- a/snmp.go +++ b/snmp.go @@ -207,6 +207,30 @@ func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) { if addToParent { t.nodes.Update([]net.IP{deviceIP}, []net.HardwareAddr{mac}, "", "", "snmp") } else { + t.nodes.mu.RLock() + deviceNodeID := -1 + if id, exists := t.nodes.ipIndex[deviceIP.String()]; exists { + deviceNodeID = id + } + macNodeID := -1 + if id, exists := t.nodes.macIndex[mac.String()]; exists { + macNodeID = id + } + + if deviceNodeID != -1 && macNodeID != -1 { + deviceNode := t.nodes.nodes[deviceNodeID] + if deviceNode.ParentID == macNodeID { + t.nodes.mu.RUnlock() + t.nodes.mu.Lock() + if deviceNode.LocalPort == "" { + deviceNode.LocalPort = ifName + } + t.nodes.mu.Unlock() + continue + } + } + t.nodes.mu.RUnlock() + t.nodes.UpdateWithParent(deviceIP, nil, []net.HardwareAddr{mac}, ifName, "", "snmp") } } @@ -280,6 +304,30 @@ func (t *Tendrils) queryARPTable(snmp *gosnmp.GoSNMP, deviceIP net.IP) { ifName = "??" } + t.nodes.mu.RLock() + deviceNodeID := -1 + if id, exists := t.nodes.ipIndex[deviceIP.String()]; exists { + deviceNodeID = id + } + macNodeID := -1 + if id, exists := t.nodes.macIndex[mac.String()]; exists { + macNodeID = id + } + + if deviceNodeID != -1 && macNodeID != -1 { + deviceNode := t.nodes.nodes[deviceNodeID] + if deviceNode.ParentID == macNodeID { + t.nodes.mu.RUnlock() + t.nodes.mu.Lock() + if deviceNode.LocalPort == "" { + deviceNode.LocalPort = ifName + } + t.nodes.mu.Unlock() + continue + } + } + t.nodes.mu.RUnlock() + t.nodes.UpdateWithParent(deviceIP, ips, []net.HardwareAddr{mac}, ifName, "", "snmp") } } diff --git a/tendrils.go b/tendrils.go index 4b40529..2c8fdfe 100644 --- a/tendrils.go +++ b/tendrils.go @@ -23,6 +23,8 @@ func (t *Tendrils) Run() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() + t.populateLocalAddresses() + go t.pollARP(ctx) go t.pollSNMP(ctx) @@ -36,6 +38,41 @@ func (t *Tendrils) Run() { } } +func (t *Tendrils) populateLocalAddresses() { + interfaces, err := net.Interfaces() + if err != nil { + return + } + + t.nodes.mu.Lock() + defer t.nodes.mu.Unlock() + + root := t.nodes.nodes[0] + + for _, iface := range interfaces { + if len(iface.HardwareAddr) > 0 { + macKey := iface.HardwareAddr.String() + root.MACs[macKey] = iface.HardwareAddr + t.nodes.macIndex[macKey] = 0 + } + + addrs, err := iface.Addrs() + if err != nil { + continue + } + + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok { + if ipnet.IP.To4() != nil && !ipnet.IP.IsLoopback() { + ipKey := ipnet.IP.String() + root.IPs[ipKey] = ipnet.IP + t.nodes.ipIndex[ipKey] = 0 + } + } + } + } +} + func (t *Tendrils) listInterfaces() []net.Interface { interfaces, err := net.Interfaces() if err != nil {