master
go 104 lines 2.9 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 package snmp
4
5 import (
6 "errors"
7 "fmt"
8 "time"
9
10 "github.com/google/uuid"
11 "github.com/gosnmp/gosnmp"
12
13 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/pinger"
14 "github.com/netdata/netdata/go/plugins/plugin/go.d/pkg/snmputils"
15 )
16
17 func (c *Collector) validateConfig() error {
18 if c.Hostname == "" {
19 return errors.New("SNMP hostname is required")
20 }
21 if c.Vnode.GUID != "" {
22 if err := uuid.Validate(c.Vnode.GUID); err != nil {
23 return fmt.Errorf("invalid Vnode GUID: %v", err)
24 }
25 }
26 return nil
27 }
28
29 func (c *Collector) initSNMPClient() (gosnmp.Handler, error) {
30 client, err := c.newConfiguredSNMPClient()
31 if err != nil {
32 return nil, err
33 }
34
35 c.Info(snmputils.SnmpClientConnInfo(client))
36
37 return client, nil
38 }
39
40 func (c *Collector) newConfiguredSNMPClient() (gosnmp.Handler, error) {
41 client := c.newSnmpClient()
42
43 client.SetTarget(c.Hostname)
44 client.SetPort(uint16(c.Options.Port))
45 client.SetRetries(c.Options.Retries)
46 client.SetTimeout(time.Duration(c.Options.Timeout) * time.Second)
47 client.SetMaxOids(c.Options.MaxOIDs)
48 client.SetMaxRepetitions(uint32(c.Options.MaxRepetitions))
49
50 ver := snmputils.ParseSNMPVersion(c.Options.Version)
51 comm := c.Community
52
53 switch ver {
54 case gosnmp.Version1:
55 client.SetCommunity(comm)
56 client.SetVersion(gosnmp.Version1)
57 case gosnmp.Version2c:
58 client.SetCommunity(comm)
59 client.SetVersion(gosnmp.Version2c)
60 case gosnmp.Version3:
61 if c.User.Name == "" {
62 return nil, errors.New("username is required for SNMPv3")
63 }
64 client.SetVersion(gosnmp.Version3)
65 client.SetSecurityModel(gosnmp.UserSecurityModel)
66 client.SetMsgFlags(snmputils.ParseSNMPv3SecurityLevel(c.User.SecurityLevel))
67 client.SetSecurityParameters(&gosnmp.UsmSecurityParameters{
68 UserName: c.User.Name,
69 AuthenticationProtocol: snmputils.ParseSNMPv3AuthProtocol(c.User.AuthProto),
70 AuthenticationPassphrase: c.User.AuthKey,
71 PrivacyProtocol: snmputils.ParseSNMPv3PrivProtocol(c.User.PrivProto),
72 PrivacyPassphrase: c.User.PrivKey,
73 })
74 // Context name addresses a specific MIB view on multi-context
75 // agents (virtual routers, logical partitions, snmpsim virtual
76 // devices). Empty string means the default context.
77 client.SetContextName(c.User.ContextName)
78 default:
79 return nil, fmt.Errorf("invalid SNMP version: %s", c.Options.Version)
80 }
81
82 return client, nil
83 }
84
85 func (c *Collector) initPinger() (pinger.Client, error) {
86 // base timeout = update_every seconds
87 timeout := time.Duration(c.UpdateEvery) * time.Second
88
89 // clamp between 1s and 3s
90 const minTimeout = time.Second
91 const maxTimeout = 3 * time.Second
92 timeout = max(min(timeout, maxTimeout), minTimeout)
93
94 return c.newPinger(pinger.Config{
95 Probe: pinger.ProbeConfig{
96 Network: c.Ping.Network,
97 Interface: c.Ping.Interface,
98 Privileged: c.Ping.Privileged,
99 Packets: c.Ping.Packets,
100 Interval: c.Ping.Interval,
101 Timeout: timeout,
102 },
103 }, c.Logger)
104 }