Interpret SNMP v1 traps as described in RFC 2576 3.1 (#6793)
This commit is contained in:
parent
7cc3507f22
commit
cae701c54b
plugins/inputs/snmp_trap
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -150,6 +151,12 @@ func (s *SnmpTrap) Stop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setTrapOid(tags map[string]string, oid string, e mibEntry) {
|
||||||
|
tags["oid"] = oid
|
||||||
|
tags["name"] = e.oidText
|
||||||
|
tags["mib"] = e.mibName
|
||||||
|
}
|
||||||
|
|
||||||
func makeTrapHandler(s *SnmpTrap) handler {
|
func makeTrapHandler(s *SnmpTrap) handler {
|
||||||
return func(packet *gosnmp.SnmpPacket, addr *net.UDPAddr) {
|
return func(packet *gosnmp.SnmpPacket, addr *net.UDPAddr) {
|
||||||
tm := s.timeFunc()
|
tm := s.timeFunc()
|
||||||
|
@ -159,6 +166,33 @@ func makeTrapHandler(s *SnmpTrap) handler {
|
||||||
tags["version"] = packet.Version.String()
|
tags["version"] = packet.Version.String()
|
||||||
tags["source"] = addr.IP.String()
|
tags["source"] = addr.IP.String()
|
||||||
|
|
||||||
|
if packet.Version == gosnmp.Version1 {
|
||||||
|
// Follow the procedure described in RFC 2576 3.1 to
|
||||||
|
// translate a v1 trap to v2.
|
||||||
|
var trapOid string
|
||||||
|
|
||||||
|
if packet.GenericTrap > 0 && packet.GenericTrap < 6 {
|
||||||
|
trapOid = "1.3.6.1.6.3.1.1.5." + strconv.Itoa(packet.GenericTrap+1)
|
||||||
|
} else if packet.GenericTrap == 6 {
|
||||||
|
trapOid = packet.Enterprise + ".0." + strconv.Itoa(packet.SpecificTrap)
|
||||||
|
}
|
||||||
|
|
||||||
|
if trapOid != "" {
|
||||||
|
e, err := s.lookup(trapOid)
|
||||||
|
if err != nil {
|
||||||
|
s.Log.Errorf("Error resolving V1 OID: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setTrapOid(tags, trapOid, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if packet.AgentAddress != "" {
|
||||||
|
tags["agent_address"] = packet.AgentAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
fields["sysUpTimeInstance"] = packet.Timestamp
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range packet.Variables {
|
for _, v := range packet.Variables {
|
||||||
// Use system mibs to resolve oids. Don't fall back to
|
// Use system mibs to resolve oids. Don't fall back to
|
||||||
// numeric oid because it's not useful enough to the end
|
// numeric oid because it's not useful enough to the end
|
||||||
|
@ -193,9 +227,7 @@ func makeTrapHandler(s *SnmpTrap) handler {
|
||||||
// 1.3.6.1.6.3.1.1.4.1.0 is SNMPv2-MIB::snmpTrapOID.0.
|
// 1.3.6.1.6.3.1.1.4.1.0 is SNMPv2-MIB::snmpTrapOID.0.
|
||||||
// If v.Name is this oid, set a tag of the trap name.
|
// If v.Name is this oid, set a tag of the trap name.
|
||||||
if v.Name == ".1.3.6.1.6.3.1.1.4.1.0" {
|
if v.Name == ".1.3.6.1.6.3.1.1.4.1.0" {
|
||||||
tags["oid"] = val
|
setTrapOid(tags, val, e)
|
||||||
tags["name"] = e.oidText
|
|
||||||
tags["mib"] = e.mibName
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -220,3 +220,115 @@ func TestMissingOid(t *testing.T) {
|
||||||
expected, acc.GetTelegrafMetrics(),
|
expected, acc.GetTelegrafMetrics(),
|
||||||
testutil.SortMetrics())
|
testutil.SortMetrics())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendV1Trap(t *testing.T, port uint16) (sentTimestamp uint) {
|
||||||
|
s := &gosnmp.GoSNMP{
|
||||||
|
Port: port,
|
||||||
|
Community: "public",
|
||||||
|
Version: gosnmp.Version1,
|
||||||
|
Timeout: time.Duration(2) * time.Second,
|
||||||
|
Retries: 3,
|
||||||
|
MaxOids: gosnmp.MaxOids,
|
||||||
|
Target: "127.0.0.1",
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.Connect()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Connect() err: %v", err)
|
||||||
|
}
|
||||||
|
defer s.Conn.Close()
|
||||||
|
|
||||||
|
now := uint(time.Now().Unix())
|
||||||
|
|
||||||
|
pdu := gosnmp.SnmpPDU{
|
||||||
|
Name: ".1.2.3.4.5",
|
||||||
|
Type: gosnmp.OctetString,
|
||||||
|
Value: "payload",
|
||||||
|
}
|
||||||
|
|
||||||
|
trap := gosnmp.SnmpTrap{
|
||||||
|
Variables: []gosnmp.SnmpPDU{pdu},
|
||||||
|
Enterprise: ".1.2.3",
|
||||||
|
AgentAddress: "10.20.30.40",
|
||||||
|
GenericTrap: 6, // enterpriseSpecific
|
||||||
|
SpecificTrap: 55,
|
||||||
|
Timestamp: now,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.SendTrap(trap)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("SendTrap() err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return now
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReceiveV1Trap(t *testing.T) {
|
||||||
|
const port = 12399
|
||||||
|
var fakeTime = time.Now()
|
||||||
|
|
||||||
|
received := make(chan int)
|
||||||
|
wrap := func(f handler) handler {
|
||||||
|
return func(p *gosnmp.SnmpPacket, a *net.UDPAddr) {
|
||||||
|
f(p, a)
|
||||||
|
received <- 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &SnmpTrap{
|
||||||
|
ServiceAddress: "udp://:" + strconv.Itoa(port),
|
||||||
|
makeHandlerWrapper: wrap,
|
||||||
|
timeFunc: func() time.Time {
|
||||||
|
return fakeTime
|
||||||
|
},
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
}
|
||||||
|
require.Nil(t, s.Init())
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
require.Nil(t, s.Start(&acc))
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
defer s.clear()
|
||||||
|
s.load(".1.2.3.4.5",
|
||||||
|
mibEntry{
|
||||||
|
"valueMIB",
|
||||||
|
"valueOID",
|
||||||
|
})
|
||||||
|
s.load(".1.2.3.0.55",
|
||||||
|
mibEntry{
|
||||||
|
"enterpriseMIB",
|
||||||
|
"enterpriseOID",
|
||||||
|
})
|
||||||
|
|
||||||
|
sentTimestamp := sendV1Trap(t, port)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-received:
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
t.Fatal("timed out waiting for trap to be received")
|
||||||
|
}
|
||||||
|
|
||||||
|
expected := []telegraf.Metric{
|
||||||
|
testutil.MustMetric(
|
||||||
|
"snmp_trap", // name
|
||||||
|
map[string]string{ // tags
|
||||||
|
"oid": ".1.2.3.0.55",
|
||||||
|
"name": "enterpriseOID",
|
||||||
|
"mib": "enterpriseMIB",
|
||||||
|
"version": "1",
|
||||||
|
"source": "127.0.0.1",
|
||||||
|
"agent_address": "10.20.30.40",
|
||||||
|
},
|
||||||
|
map[string]interface{}{ // fields
|
||||||
|
"sysUpTimeInstance": sentTimestamp,
|
||||||
|
"valueOID": "payload",
|
||||||
|
},
|
||||||
|
fakeTime,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
testutil.RequireMetricsEqual(t,
|
||||||
|
expected, acc.GetTelegrafMetrics(),
|
||||||
|
testutil.SortMetrics())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue