Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
138
plugins/inputs/snmp_trap/README.md
Normal file
138
plugins/inputs/snmp_trap/README.md
Normal file
|
@ -0,0 +1,138 @@
|
|||
# SNMP Trap Input Plugin
|
||||
|
||||
The SNMP Trap plugin is a service input plugin that receives SNMP
|
||||
notifications (traps and inform requests).
|
||||
|
||||
Notifications are received on plain UDP. The port to listen is
|
||||
configurable.
|
||||
|
||||
## Note about Paths
|
||||
|
||||
Path is a global variable, separate snmp instances will append the specified
|
||||
path onto the global path variable
|
||||
|
||||
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
|
||||
|
||||
In addition to the plugin-specific configuration settings, plugins support
|
||||
additional global and plugin configuration settings. These settings are used to
|
||||
modify metrics, tags, and field or create aliases and configure ordering, etc.
|
||||
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||
|
||||
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
|
||||
|
||||
## Secret-store support
|
||||
|
||||
This plugin supports secrets from secret-stores for the `sec_name`,
|
||||
`auth_password` and `priv_password` option.
|
||||
See the [secret-store documentation][SECRETSTORE] for more details on how
|
||||
to use them.
|
||||
|
||||
[SECRETSTORE]: ../../../docs/CONFIGURATION.md#secret-store-secrets
|
||||
|
||||
## SNMP backend: gosmi and netsnmp
|
||||
|
||||
Telegraf has two backends to translate SNMP objects. By default, Telegraf will
|
||||
use `netsnmp`, however, this option is deprecated and it is encouraged that
|
||||
users migrate to `gosmi`. If users find issues with `gosmi` that do not occur
|
||||
with `netsnmp` please open a project issue on GitHub.
|
||||
|
||||
The SNMP backend setting is a global-level setting that applies to all use of
|
||||
SNMP in Telegraf. Users can set this option in the `[agent]` configuration via
|
||||
the `snmp_translator` option. See the [agent configuration][AGENT] for more
|
||||
details.
|
||||
|
||||
[AGENT]: ../../../docs/CONFIGURATION.md#agent
|
||||
|
||||
## Configuration
|
||||
|
||||
```toml @sample.conf
|
||||
# Receive SNMP traps
|
||||
[[inputs.snmp_trap]]
|
||||
## Transport, local address, and port to listen on. Transport must
|
||||
## be "udp://". Omit local address to listen on all interfaces.
|
||||
## example: "udp://127.0.0.1:1234"
|
||||
##
|
||||
## Special permissions may be required to listen on a port less than
|
||||
## 1024. See README.md for details
|
||||
##
|
||||
# service_address = "udp://:162"
|
||||
##
|
||||
## Path to mib files
|
||||
## Used by the gosmi translator.
|
||||
## To add paths when translating with netsnmp, use the MIBDIRS environment variable
|
||||
# path = ["/usr/share/snmp/mibs"]
|
||||
##
|
||||
## Timeout running snmptranslate command
|
||||
## Used by the netsnmp translator only
|
||||
# timeout = "5s"
|
||||
## Snmp version; one of "1", "2c" or "3".
|
||||
# version = "2c"
|
||||
## SNMPv3 authentication and encryption options.
|
||||
##
|
||||
## Security Name.
|
||||
# sec_name = "myuser"
|
||||
## Authentication protocol; one of "MD5", "SHA", "SHA224", "SHA256", "SHA384", "SHA512" or "".
|
||||
# auth_protocol = "MD5"
|
||||
## Authentication password.
|
||||
# auth_password = "pass"
|
||||
## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv".
|
||||
# sec_level = "authNoPriv"
|
||||
## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "".
|
||||
# priv_protocol = ""
|
||||
## Privacy password used for encrypted messages.
|
||||
# priv_password = ""
|
||||
```
|
||||
|
||||
### Using a Privileged Port
|
||||
|
||||
On many operating systems, listening on a privileged port (a port
|
||||
number less than 1024) requires extra permission. Since the default
|
||||
SNMP trap port 162 is in this category, using telegraf to receive SNMP
|
||||
traps may need extra permission.
|
||||
|
||||
Instructions for listening on a privileged port vary by operating
|
||||
system. It is not recommended to run telegraf as superuser in order to
|
||||
use a privileged port. Instead follow the principle of least privilege
|
||||
and use a more specific operating system mechanism to allow telegraf to
|
||||
use the port. You may also be able to have telegraf use an
|
||||
unprivileged port and then configure a firewall port forward rule from
|
||||
the privileged port.
|
||||
|
||||
To use a privileged port on Linux, you can use setcap to enable the
|
||||
CAP_NET_BIND_SERVICE capability on the telegraf binary:
|
||||
|
||||
```shell
|
||||
setcap cap_net_bind_service=+ep /usr/bin/telegraf
|
||||
```
|
||||
|
||||
On Mac OS, listening on privileged ports is unrestricted on versions
|
||||
10.14 and later.
|
||||
|
||||
## Metrics
|
||||
|
||||
- snmp_trap
|
||||
- tags:
|
||||
- source (string, IP address of trap source)
|
||||
- name (string, value from SNMPv2-MIB::snmpTrapOID.0 PDU)
|
||||
- mib (string, MIB from SNMPv2-MIB::snmpTrapOID.0 PDU)
|
||||
- oid (string, OID string from SNMPv2-MIB::snmpTrapOID.0 PDU)
|
||||
- version (string, "1" or "2c" or "3")
|
||||
- context_name (string, value from v3 trap)
|
||||
- engine_id (string, value from v3 trap)
|
||||
- community (string, value from 1 or 2c trap)
|
||||
- fields:
|
||||
- Fields are mapped from variables in the trap. Field names are
|
||||
the trap variable names after MIB lookup. Field values are trap
|
||||
variable values.
|
||||
|
||||
## Example Output
|
||||
|
||||
```text
|
||||
snmp_trap,mib=SNMPv2-MIB,name=coldStart,oid=.1.3.6.1.6.3.1.1.5.1,source=192.168.122.102,version=2c,community=public snmpTrapEnterprise.0="linux",sysUpTimeInstance=1i 1574109187723429814
|
||||
snmp_trap,mib=NET-SNMP-AGENT-MIB,name=nsNotifyShutdown,oid=.1.3.6.1.4.1.8072.4.0.2,source=192.168.122.102,version=2c,community=public sysUpTimeInstance=5803i,snmpTrapEnterprise.0="netSnmpNotificationPrefix" 1574109186555115459
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [net-snmp project home](http://www.net-snmp.org)
|
||||
- [`snmpcmd` man-page](http://net-snmp.sourceforge.net/docs/man/snmpcmd.html)
|
21
plugins/inputs/snmp_trap/gosmi.go
Normal file
21
plugins/inputs/snmp_trap/gosmi.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
package snmp_trap
|
||||
|
||||
import (
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/internal/snmp"
|
||||
)
|
||||
|
||||
type gosmiTranslator struct {
|
||||
}
|
||||
|
||||
func (*gosmiTranslator) lookup(oid string) (snmp.MibEntry, error) {
|
||||
return snmp.TrapLookup(oid)
|
||||
}
|
||||
|
||||
func newGosmiTranslator(paths []string, log telegraf.Logger) (*gosmiTranslator, error) {
|
||||
err := snmp.LoadMibsFromPath(paths, log, &snmp.GosmiMibLoader{})
|
||||
if err == nil {
|
||||
return &gosmiTranslator{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
17
plugins/inputs/snmp_trap/logger.go
Normal file
17
plugins/inputs/snmp_trap/logger.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package snmp_trap
|
||||
|
||||
import "github.com/influxdata/telegraf"
|
||||
|
||||
type logger struct {
|
||||
telegraf.Logger
|
||||
}
|
||||
|
||||
// Printf formats and writes the given string to the standard output.
|
||||
func (l logger) Printf(format string, args ...interface{}) {
|
||||
l.Tracef(format, args...)
|
||||
}
|
||||
|
||||
// Print writes the given string to the standard output.
|
||||
func (l logger) Print(args ...interface{}) {
|
||||
l.Trace(args...)
|
||||
}
|
91
plugins/inputs/snmp_trap/netsnmp.go
Normal file
91
plugins/inputs/snmp_trap/netsnmp.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
package snmp_trap
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/internal"
|
||||
"github.com/influxdata/telegraf/internal/snmp"
|
||||
)
|
||||
|
||||
type execer func(config.Duration, string, ...string) ([]byte, error)
|
||||
|
||||
func realExecCmd(timeout config.Duration, arg0 string, args ...string) ([]byte, error) {
|
||||
cmd := exec.Command(arg0, args...)
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err := internal.RunTimeout(cmd, time.Duration(timeout))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
type netsnmpTranslator struct {
|
||||
// Each translator has its own cache and each plugin instance has
|
||||
// its own translator. This is different than the snmp plugin
|
||||
// which has one global cache.
|
||||
//
|
||||
// We may want to change snmp_trap to
|
||||
// have a global cache although it's not as important for
|
||||
// snmp_trap to be global because there is usually only one
|
||||
// instance, while it's common to configure many snmp instances.
|
||||
cacheLock sync.Mutex
|
||||
cache map[string]snmp.MibEntry
|
||||
execCmd execer
|
||||
timeout config.Duration
|
||||
}
|
||||
|
||||
func (s *netsnmpTranslator) lookup(oid string) (e snmp.MibEntry, err error) {
|
||||
s.cacheLock.Lock()
|
||||
defer s.cacheLock.Unlock()
|
||||
var ok bool
|
||||
if e, ok = s.cache[oid]; !ok {
|
||||
// cache miss. exec snmptranslate
|
||||
e, err = s.snmptranslate(oid)
|
||||
if err == nil {
|
||||
s.cache[oid] = e
|
||||
}
|
||||
return e, err
|
||||
}
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func (s *netsnmpTranslator) snmptranslate(oid string) (e snmp.MibEntry, err error) {
|
||||
var out []byte
|
||||
out, err = s.execCmd(s.timeout, "snmptranslate", "-Td", "-Ob", "-m", "all", oid)
|
||||
|
||||
if err != nil {
|
||||
return e, err
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(bytes.NewBuffer(out))
|
||||
ok := scanner.Scan()
|
||||
if err = scanner.Err(); !ok && err != nil {
|
||||
return e, err
|
||||
}
|
||||
|
||||
e.OidText = scanner.Text()
|
||||
|
||||
i := strings.Index(e.OidText, "::")
|
||||
if i == -1 {
|
||||
return e, errors.New("not found")
|
||||
}
|
||||
e.MibName = e.OidText[:i]
|
||||
e.OidText = e.OidText[i+2:]
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func newNetsnmpTranslator(timeout config.Duration) *netsnmpTranslator {
|
||||
return &netsnmpTranslator{
|
||||
execCmd: realExecCmd,
|
||||
cache: make(map[string]snmp.MibEntry),
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
35
plugins/inputs/snmp_trap/sample.conf
Normal file
35
plugins/inputs/snmp_trap/sample.conf
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Receive SNMP traps
|
||||
[[inputs.snmp_trap]]
|
||||
## Transport, local address, and port to listen on. Transport must
|
||||
## be "udp://". Omit local address to listen on all interfaces.
|
||||
## example: "udp://127.0.0.1:1234"
|
||||
##
|
||||
## Special permissions may be required to listen on a port less than
|
||||
## 1024. See README.md for details
|
||||
##
|
||||
# service_address = "udp://:162"
|
||||
##
|
||||
## Path to mib files
|
||||
## Used by the gosmi translator.
|
||||
## To add paths when translating with netsnmp, use the MIBDIRS environment variable
|
||||
# path = ["/usr/share/snmp/mibs"]
|
||||
##
|
||||
## Timeout running snmptranslate command
|
||||
## Used by the netsnmp translator only
|
||||
# timeout = "5s"
|
||||
## Snmp version; one of "1", "2c" or "3".
|
||||
# version = "2c"
|
||||
## SNMPv3 authentication and encryption options.
|
||||
##
|
||||
## Security Name.
|
||||
# sec_name = "myuser"
|
||||
## Authentication protocol; one of "MD5", "SHA", "SHA224", "SHA256", "SHA384", "SHA512" or "".
|
||||
# auth_protocol = "MD5"
|
||||
## Authentication password.
|
||||
# auth_password = "pass"
|
||||
## Security Level; one of "noAuthNoPriv", "authNoPriv", or "authPriv".
|
||||
# sec_level = "authNoPriv"
|
||||
## Privacy protocol used for encrypted messages; one of "DES", "AES", "AES192", "AES192C", "AES256", "AES256C" or "".
|
||||
# priv_protocol = ""
|
||||
## Privacy password used for encrypted messages.
|
||||
# priv_password = ""
|
355
plugins/inputs/snmp_trap/snmp_trap.go
Normal file
355
plugins/inputs/snmp_trap/snmp_trap.go
Normal file
|
@ -0,0 +1,355 @@
|
|||
//go:generate ../../../tools/readme_config_includer/generator
|
||||
package snmp_trap
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/gosnmp/gosnmp"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
"github.com/influxdata/telegraf/config"
|
||||
"github.com/influxdata/telegraf/internal/snmp"
|
||||
"github.com/influxdata/telegraf/plugins/inputs"
|
||||
)
|
||||
|
||||
var defaultTimeout = config.Duration(time.Second * 5)
|
||||
|
||||
//go:embed sample.conf
|
||||
var sampleConfig string
|
||||
|
||||
type SnmpTrap struct {
|
||||
ServiceAddress string `toml:"service_address"`
|
||||
Timeout config.Duration `toml:"timeout"`
|
||||
Version string `toml:"version"`
|
||||
Path []string `toml:"path"`
|
||||
|
||||
// Settings for version 3 security
|
||||
SecLevel string `toml:"sec_level"`
|
||||
SecName config.Secret `toml:"sec_name"`
|
||||
AuthProtocol string `toml:"auth_protocol"`
|
||||
AuthPassword config.Secret `toml:"auth_password"`
|
||||
PrivProtocol string `toml:"priv_protocol"`
|
||||
PrivPassword config.Secret `toml:"priv_password"`
|
||||
|
||||
Translator string `toml:"-"`
|
||||
Log telegraf.Logger `toml:"-"`
|
||||
|
||||
acc telegraf.Accumulator
|
||||
listener *gosnmp.TrapListener
|
||||
|
||||
transl translator
|
||||
}
|
||||
|
||||
type translator interface {
|
||||
lookup(oid string) (snmp.MibEntry, error)
|
||||
}
|
||||
|
||||
func (*SnmpTrap) SampleConfig() string {
|
||||
return sampleConfig
|
||||
}
|
||||
|
||||
func (s *SnmpTrap) SetTranslator(name string) {
|
||||
s.Translator = name
|
||||
}
|
||||
|
||||
func (s *SnmpTrap) Init() error {
|
||||
// Set defaults
|
||||
if s.ServiceAddress == "" {
|
||||
s.ServiceAddress = "udp://:162"
|
||||
}
|
||||
|
||||
if len(s.Path) == 0 {
|
||||
s.Path = []string{"/usr/share/snmp/mibs"}
|
||||
}
|
||||
|
||||
// Check input parameters
|
||||
switch s.Translator {
|
||||
case "gosmi":
|
||||
t, err := newGosmiTranslator(s.Path, s.Log)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.transl = t
|
||||
case "netsnmp":
|
||||
s.transl = newNetsnmpTranslator(s.Timeout)
|
||||
default:
|
||||
// Ignore the translator for testing if an instance was set
|
||||
if s.transl == nil {
|
||||
return errors.New("invalid translator value")
|
||||
}
|
||||
}
|
||||
|
||||
// Setup the SNMP parameters
|
||||
params := *gosnmp.Default
|
||||
if s.Log.Level().Includes(telegraf.Trace) {
|
||||
params.Logger = gosnmp.NewLogger(&logger{s.Log})
|
||||
}
|
||||
|
||||
switch s.Version {
|
||||
case "1":
|
||||
params.Version = gosnmp.Version1
|
||||
case "", "2c":
|
||||
params.Version = gosnmp.Version2c
|
||||
case "3":
|
||||
params.Version = gosnmp.Version3
|
||||
|
||||
// Setup the security for v3
|
||||
params.SecurityModel = gosnmp.UserSecurityModel
|
||||
|
||||
// Set security mechanisms
|
||||
switch strings.ToLower(s.SecLevel) {
|
||||
case "noauthnopriv", "":
|
||||
params.MsgFlags = gosnmp.NoAuthNoPriv
|
||||
case "authnopriv":
|
||||
params.MsgFlags = gosnmp.AuthNoPriv
|
||||
case "authpriv":
|
||||
params.MsgFlags = gosnmp.AuthPriv
|
||||
default:
|
||||
return fmt.Errorf("unknown security level %q", s.SecLevel)
|
||||
}
|
||||
|
||||
// Set authentication
|
||||
var security gosnmp.UsmSecurityParameters
|
||||
switch strings.ToLower(s.AuthProtocol) {
|
||||
case "":
|
||||
security.AuthenticationProtocol = gosnmp.NoAuth
|
||||
case "md5":
|
||||
security.AuthenticationProtocol = gosnmp.MD5
|
||||
case "sha":
|
||||
security.AuthenticationProtocol = gosnmp.SHA
|
||||
case "sha224":
|
||||
security.AuthenticationProtocol = gosnmp.SHA224
|
||||
case "sha256":
|
||||
security.AuthenticationProtocol = gosnmp.SHA256
|
||||
case "sha384":
|
||||
security.AuthenticationProtocol = gosnmp.SHA384
|
||||
case "sha512":
|
||||
security.AuthenticationProtocol = gosnmp.SHA512
|
||||
default:
|
||||
return fmt.Errorf("unknown authentication protocol %q", s.AuthProtocol)
|
||||
}
|
||||
|
||||
// Set privacy
|
||||
switch strings.ToLower(s.PrivProtocol) {
|
||||
case "":
|
||||
security.PrivacyProtocol = gosnmp.NoPriv
|
||||
case "aes":
|
||||
security.PrivacyProtocol = gosnmp.AES
|
||||
case "des":
|
||||
security.PrivacyProtocol = gosnmp.DES
|
||||
case "aes192":
|
||||
security.PrivacyProtocol = gosnmp.AES192
|
||||
case "aes192c":
|
||||
security.PrivacyProtocol = gosnmp.AES192C
|
||||
case "aes256":
|
||||
security.PrivacyProtocol = gosnmp.AES256
|
||||
case "aes256c":
|
||||
security.PrivacyProtocol = gosnmp.AES256C
|
||||
default:
|
||||
return fmt.Errorf("unknown privacy protocol %q", s.PrivProtocol)
|
||||
}
|
||||
|
||||
// Set credentials
|
||||
secnameSecret, err := s.SecName.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting secname failed: %w", err)
|
||||
}
|
||||
security.UserName = secnameSecret.String()
|
||||
secnameSecret.Destroy()
|
||||
|
||||
authPasswdSecret, err := s.AuthPassword.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting auth-password failed: %w", err)
|
||||
}
|
||||
security.AuthenticationPassphrase = authPasswdSecret.String()
|
||||
authPasswdSecret.Destroy()
|
||||
|
||||
privPasswdSecret, err := s.PrivPassword.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting priv-password failed: %w", err)
|
||||
}
|
||||
security.PrivacyPassphrase = privPasswdSecret.String()
|
||||
privPasswdSecret.Destroy()
|
||||
|
||||
// Enable security settings
|
||||
params.SecurityParameters = &security
|
||||
default:
|
||||
return fmt.Errorf("unknown version %q", s.Version)
|
||||
}
|
||||
|
||||
// Initialize the listener
|
||||
s.listener = gosnmp.NewTrapListener()
|
||||
s.listener.OnNewTrap = s.handler
|
||||
s.listener.Params = ¶ms
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SnmpTrap) Start(acc telegraf.Accumulator) error {
|
||||
s.acc = acc
|
||||
|
||||
u, err := url.Parse(s.ServiceAddress)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid service address: %s", s.ServiceAddress)
|
||||
}
|
||||
|
||||
// The gosnmp package currently only supports UDP
|
||||
if u.Scheme != "udp" {
|
||||
return fmt.Errorf("unknown protocol for service address %q", s.ServiceAddress)
|
||||
}
|
||||
|
||||
// If the listener immediately returns an error we need to return it
|
||||
errCh := make(chan error, 1)
|
||||
go func() {
|
||||
errCh <- s.listener.Listen(u.Host)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-s.listener.Listening():
|
||||
s.Log.Infof("Listening on %s", s.ServiceAddress)
|
||||
case err := <-errCh:
|
||||
return fmt.Errorf("listening failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*SnmpTrap) Gather(telegraf.Accumulator) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SnmpTrap) Stop() {
|
||||
s.listener.Close()
|
||||
}
|
||||
|
||||
func setTrapOid(tags map[string]string, oid string, e snmp.MibEntry) {
|
||||
tags["oid"] = oid
|
||||
tags["name"] = e.OidText
|
||||
tags["mib"] = e.MibName
|
||||
}
|
||||
|
||||
func (s *SnmpTrap) handler(packet *gosnmp.SnmpPacket, addr *net.UDPAddr) {
|
||||
tm := time.Now()
|
||||
fields := make(map[string]interface{}, len(packet.Variables)+1)
|
||||
tags := map[string]string{
|
||||
"version": packet.Version.String(),
|
||||
"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.transl.lookup(trapOid)
|
||||
if err != nil {
|
||||
s.Log.Errorf("Error resolving V1 OID, oid=%s, source=%s: %v", trapOid, tags["source"], err)
|
||||
return
|
||||
}
|
||||
setTrapOid(tags, trapOid, e)
|
||||
}
|
||||
|
||||
if packet.AgentAddress != "" {
|
||||
tags["agent_address"] = packet.AgentAddress
|
||||
}
|
||||
|
||||
fields["sysUpTimeInstance"] = packet.Timestamp
|
||||
}
|
||||
|
||||
for _, v := range packet.Variables {
|
||||
var value interface{}
|
||||
|
||||
// Use system mibs to resolve oids. Don't fall back to numeric oid
|
||||
// because it's not useful enough to the end user and can be difficult
|
||||
// to translate or remove from the database later.
|
||||
//
|
||||
// TODO: format the pdu value based on its snmp type and the mib's
|
||||
// textual convention. The snmp input plugin only handles textual
|
||||
// convention for ip and mac addresses
|
||||
switch v.Type {
|
||||
case gosnmp.ObjectIdentifier:
|
||||
val, ok := v.Value.(string)
|
||||
if !ok {
|
||||
s.Log.Errorf("Error getting value OID")
|
||||
return
|
||||
}
|
||||
|
||||
var e snmp.MibEntry
|
||||
var err error
|
||||
e, err = s.transl.lookup(val)
|
||||
if nil != err {
|
||||
s.Log.Errorf("Error resolving value OID, oid=%s, source=%s: %v", val, tags["source"], err)
|
||||
return
|
||||
}
|
||||
|
||||
value = e.OidText
|
||||
|
||||
// 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 == ".1.3.6.1.6.3.1.1.4.1.0" {
|
||||
setTrapOid(tags, val, e)
|
||||
continue
|
||||
}
|
||||
case gosnmp.OctetString:
|
||||
// OctetStrings may contain hex data that needs its own conversion
|
||||
if !utf8.Valid(v.Value.([]byte)[:]) {
|
||||
value = hex.EncodeToString(v.Value.([]byte))
|
||||
} else {
|
||||
value = v.Value
|
||||
}
|
||||
default:
|
||||
value = v.Value
|
||||
}
|
||||
|
||||
e, err := s.transl.lookup(v.Name)
|
||||
if nil != err {
|
||||
s.Log.Errorf("Error resolving OID oid=%s, source=%s: %v", v.Name, tags["source"], err)
|
||||
return
|
||||
}
|
||||
|
||||
fields[e.OidText] = value
|
||||
}
|
||||
|
||||
if packet.Version == gosnmp.Version3 {
|
||||
if packet.ContextName != "" {
|
||||
tags["context_name"] = packet.ContextName
|
||||
}
|
||||
if packet.ContextEngineID != "" {
|
||||
// SNMP RFCs like 3411 and 5343 show engine ID as a hex string
|
||||
tags["engine_id"] = fmt.Sprintf("%x", packet.ContextEngineID)
|
||||
}
|
||||
} else {
|
||||
if packet.Community != "" {
|
||||
tags["community"] = packet.Community
|
||||
}
|
||||
}
|
||||
|
||||
s.acc.AddFields("snmp_trap", fields, tags, tm)
|
||||
}
|
||||
|
||||
func init() {
|
||||
inputs.Add("snmp_trap", func() telegraf.Input {
|
||||
return &SnmpTrap{
|
||||
ServiceAddress: "udp://:162",
|
||||
Timeout: defaultTimeout,
|
||||
Path: []string{"/usr/share/snmp/mibs"},
|
||||
Version: "2c",
|
||||
}
|
||||
})
|
||||
}
|
1574
plugins/inputs/snmp_trap/snmp_trap_test.go
Normal file
1574
plugins/inputs/snmp_trap/snmp_trap_test.go
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue