fix local address population and snmp reverse port discovery
populate root node with local macs/ips at startup, excluding loopback addresses and permanent arp entries. detect when snmp finds parent node mac in child forwarding table and set child localport. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
5
arp.go
5
arp.go
@@ -63,6 +63,11 @@ func (t *Tendrils) parseARPDarwin() []arpEntry {
|
|||||||
scanner := bufio.NewScanner(strings.NewReader(string(output)))
|
scanner := bufio.NewScanner(strings.NewReader(string(output)))
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
|
|
||||||
|
if strings.Contains(line, "permanent") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
fields := strings.Fields(line)
|
fields := strings.Fields(line)
|
||||||
if len(fields) < 6 {
|
if len(fields) < 6 {
|
||||||
continue
|
continue
|
||||||
|
|||||||
16
nodes.go
16
nodes.go
@@ -122,14 +122,16 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw
|
|||||||
node := n.nodes[targetID]
|
node := n.nodes[targetID]
|
||||||
var added []string
|
var added []string
|
||||||
|
|
||||||
if node.LocalPort == "" && childPort != "" {
|
if targetID != 0 {
|
||||||
node.LocalPort = childPort
|
if node.LocalPort == "" && childPort != "" {
|
||||||
added = append(added, "localPort="+childPort)
|
node.LocalPort = childPort
|
||||||
}
|
added = append(added, "localPort="+childPort)
|
||||||
|
}
|
||||||
|
|
||||||
if node.ParentPort == "" && parentPort != "" {
|
if node.ParentPort == "" && parentPort != "" {
|
||||||
node.ParentPort = parentPort
|
node.ParentPort = parentPort
|
||||||
added = append(added, "parentPort="+parentPort)
|
added = append(added, "parentPort="+parentPort)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
|
|||||||
48
snmp.go
48
snmp.go
@@ -207,6 +207,30 @@ func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) {
|
|||||||
if addToParent {
|
if addToParent {
|
||||||
t.nodes.Update([]net.IP{deviceIP}, []net.HardwareAddr{mac}, "", "", "snmp")
|
t.nodes.Update([]net.IP{deviceIP}, []net.HardwareAddr{mac}, "", "", "snmp")
|
||||||
} else {
|
} 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")
|
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 = "??"
|
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")
|
t.nodes.UpdateWithParent(deviceIP, ips, []net.HardwareAddr{mac}, ifName, "", "snmp")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
37
tendrils.go
37
tendrils.go
@@ -23,6 +23,8 @@ func (t *Tendrils) Run() {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
t.populateLocalAddresses()
|
||||||
|
|
||||||
go t.pollARP(ctx)
|
go t.pollARP(ctx)
|
||||||
go t.pollSNMP(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 {
|
func (t *Tendrils) listInterfaces() []net.Interface {
|
||||||
interfaces, err := net.Interfaces()
|
interfaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user