add node names from hostname, lldp, and snmp
populate local node name from hostname. extract system name from lldp packets and snmp sysname oid. call logtree after node merges. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -6,4 +6,4 @@
|
|||||||
- Always push after commiting
|
- Always push after commiting
|
||||||
- Use git add -A so you don't miss files when committing
|
- Use git add -A so you don't miss files when committing
|
||||||
- Never use go build -- use go run instead
|
- Never use go build -- use go run instead
|
||||||
- Don't commit unless asked to
|
- DO NOT commit unless asked to
|
||||||
13
lldp.go
13
lldp.go
@@ -55,7 +55,20 @@ func (t *Tendrils) handleLLDPPacket(ifaceName string, packet gopacket.Packet) {
|
|||||||
mac := net.HardwareAddr(lldp.ChassisID.ID)
|
mac := net.HardwareAddr(lldp.ChassisID.ID)
|
||||||
if !isBroadcastOrZero(mac) {
|
if !isBroadcastOrZero(mac) {
|
||||||
childPort := string(lldp.PortID.ID)
|
childPort := string(lldp.PortID.ID)
|
||||||
|
|
||||||
|
var systemName string
|
||||||
|
for _, opt := range lldp.Values {
|
||||||
|
if opt.Type == layers.LLDPTLVSysName {
|
||||||
|
systemName = string(opt.Value)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t.nodes.Update(nil, []net.HardwareAddr{mac}, ifaceName, childPort, "lldp")
|
t.nodes.Update(nil, []net.HardwareAddr{mac}, ifaceName, childPort, "lldp")
|
||||||
|
|
||||||
|
if systemName != "" {
|
||||||
|
t.nodes.SetName(mac, systemName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
25
nodes.go
25
nodes.go
@@ -9,6 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
|
Name string
|
||||||
IPs map[string]net.IP
|
IPs map[string]net.IP
|
||||||
MACs map[string]net.HardwareAddr
|
MACs map[string]net.HardwareAddr
|
||||||
ParentID int
|
ParentID int
|
||||||
@@ -29,7 +30,12 @@ func (n *Node) String() string {
|
|||||||
}
|
}
|
||||||
sort.Strings(ips)
|
sort.Strings(ips)
|
||||||
|
|
||||||
return fmt.Sprintf("{macs=%v ips=%v}", macs, ips)
|
name := n.Name
|
||||||
|
if name == "" {
|
||||||
|
name = "??"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s {macs=%v ips=%v}", name, macs, ips)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Nodes struct {
|
type Nodes struct {
|
||||||
@@ -117,6 +123,9 @@ func (n *Nodes) UpdateWithParent(parentIP net.IP, ips []net.IP, macs []net.Hardw
|
|||||||
n.mergeNodes(targetID, ids[i])
|
n.mergeNodes(targetID, ids[i])
|
||||||
}
|
}
|
||||||
log.Printf("merged nodes %v into %s (via %s)", merging, n.nodes[targetID], source)
|
log.Printf("merged nodes %v into %s (via %s)", merging, n.nodes[targetID], source)
|
||||||
|
n.mu.Unlock()
|
||||||
|
n.LogTree()
|
||||||
|
n.mu.Lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
node := n.nodes[targetID]
|
node := n.nodes[targetID]
|
||||||
@@ -197,6 +206,18 @@ func (n *Nodes) GetByMAC(mac net.HardwareAddr) *Node {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Nodes) SetName(mac net.HardwareAddr, name string) {
|
||||||
|
n.mu.Lock()
|
||||||
|
defer n.mu.Unlock()
|
||||||
|
|
||||||
|
if id, exists := n.macIndex[mac.String()]; exists {
|
||||||
|
node := n.nodes[id]
|
||||||
|
if node.Name == "" {
|
||||||
|
node.Name = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Nodes) All() []*Node {
|
func (n *Nodes) All() []*Node {
|
||||||
n.mu.RLock()
|
n.mu.RLock()
|
||||||
defer n.mu.RUnlock()
|
defer n.mu.RUnlock()
|
||||||
@@ -219,7 +240,7 @@ func (n *Nodes) logNode(id int, prefix string, isLast bool) {
|
|||||||
node := n.nodes[id]
|
node := n.nodes[id]
|
||||||
|
|
||||||
if id == 0 {
|
if id == 0 {
|
||||||
log.Printf("[root] %s", node)
|
log.Printf("%s", node)
|
||||||
n.logChildrenByInterface(id, "")
|
n.logChildrenByInterface(id, "")
|
||||||
} else {
|
} else {
|
||||||
connector := "├──"
|
connector := "├──"
|
||||||
|
|||||||
31
snmp.go
31
snmp.go
@@ -113,9 +113,40 @@ func (t *Tendrils) querySNMPDevice(ip net.IP) {
|
|||||||
}
|
}
|
||||||
defer snmp.Conn.Close()
|
defer snmp.Conn.Close()
|
||||||
|
|
||||||
|
t.querySysName(snmp, ip)
|
||||||
t.queryBridgeMIB(snmp, ip)
|
t.queryBridgeMIB(snmp, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tendrils) querySysName(snmp *gosnmp.GoSNMP, deviceIP net.IP) {
|
||||||
|
oid := "1.3.6.1.2.1.1.5.0"
|
||||||
|
|
||||||
|
result, err := snmp.Get([]string{oid})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(result.Variables) > 0 {
|
||||||
|
variable := result.Variables[0]
|
||||||
|
if variable.Type == gosnmp.OctetString {
|
||||||
|
sysName := string(variable.Value.([]byte))
|
||||||
|
if sysName != "" {
|
||||||
|
t.nodes.mu.RLock()
|
||||||
|
if id, exists := t.nodes.ipIndex[deviceIP.String()]; exists {
|
||||||
|
t.nodes.mu.RUnlock()
|
||||||
|
t.nodes.mu.Lock()
|
||||||
|
node := t.nodes.nodes[id]
|
||||||
|
if node.Name == "" {
|
||||||
|
node.Name = sysName
|
||||||
|
}
|
||||||
|
t.nodes.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.nodes.mu.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) {
|
func (t *Tendrils) queryBridgeMIB(snmp *gosnmp.GoSNMP, deviceIP net.IP) {
|
||||||
portOID := "1.3.6.1.2.1.17.7.1.2.2.1.2"
|
portOID := "1.3.6.1.2.1.17.7.1.2.2.1.2"
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -49,6 +50,11 @@ func (t *Tendrils) populateLocalAddresses() {
|
|||||||
|
|
||||||
root := t.nodes.nodes[0]
|
root := t.nodes.nodes[0]
|
||||||
|
|
||||||
|
hostname, err := os.Hostname()
|
||||||
|
if err == nil {
|
||||||
|
root.Name = hostname
|
||||||
|
}
|
||||||
|
|
||||||
for _, iface := range interfaces {
|
for _, iface := range interfaces {
|
||||||
if len(iface.HardwareAddr) > 0 {
|
if len(iface.HardwareAddr) > 0 {
|
||||||
macKey := iface.HardwareAddr.String()
|
macKey := iface.HardwareAddr.String()
|
||||||
|
|||||||
Reference in New Issue
Block a user