github.com/netdata/go.d.plugin@v0.58.1/modules/snmp/init.go (about) 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/gosnmp/gosnmp" 11 ) 12 13 var newSNMPClient = gosnmp.NewHandler 14 15 func (s SNMP) validateConfig() error { 16 if len(s.ChartsInput) == 0 { 17 return errors.New("'charts' are required but not set") 18 } 19 20 if s.Options.Version == gosnmp.Version3.String() { 21 if s.User.Name == "" { 22 return errors.New("'user.name' is required when using SNMPv3 but not set") 23 } 24 if _, err := parseSNMPv3SecurityLevel(s.User.SecurityLevel); err != nil { 25 return err 26 } 27 if _, err := parseSNMPv3AuthProtocol(s.User.AuthProto); err != nil { 28 return err 29 } 30 if _, err := parseSNMPv3PrivProtocol(s.User.PrivProto); err != nil { 31 return err 32 } 33 } 34 35 return nil 36 } 37 38 func (s SNMP) initSNMPClient() (gosnmp.Handler, error) { 39 client := newSNMPClient() 40 41 if client.SetTarget(s.Hostname); client.Target() == "" { 42 s.Warningf("'hostname' not set, using the default value: '%s'", defaultHostname) 43 client.SetTarget(defaultHostname) 44 } 45 if client.SetPort(uint16(s.Options.Port)); client.Port() <= 0 || client.Port() > 65535 { 46 s.Warningf("'options.port' is invalid, changing to the default value: '%d' => '%d'", s.Options.Port, defaultPort) 47 client.SetPort(defaultPort) 48 } 49 if client.SetRetries(s.Options.Retries); client.Retries() < 1 || client.Retries() > 10 { 50 s.Warningf("'options.retries' is invalid, changing to the default value: '%d' => '%d'", s.Options.Retries, defaultRetries) 51 client.SetRetries(defaultRetries) 52 } 53 if client.SetTimeout(time.Duration(s.Options.Timeout) * time.Second); client.Timeout().Seconds() < 1 { 54 s.Warningf("'options.timeout' is invalid, changing to the default value: '%d' => '%d'", s.Options.Timeout, defaultTimeout) 55 client.SetTimeout(defaultTimeout * time.Second) 56 } 57 if client.SetMaxOids(s.Options.MaxOIDs); client.MaxOids() < 1 { 58 s.Warningf("'options.max_request_size' is invalid, changing to the default value: '%d' => '%d'", s.Options.MaxOIDs, defaultMaxOIDs) 59 client.SetMaxOids(defaultMaxOIDs) 60 } 61 62 ver, err := parseSNMPVersion(s.Options.Version) 63 if err != nil { 64 s.Warningf("'options.version' is invalid, changing to the default value: '%s' => '%s'", 65 s.Options.Version, defaultVersion) 66 ver = defaultVersion 67 } 68 comm := s.Community 69 if comm == "" && (ver <= gosnmp.Version2c) { 70 s.Warningf("'community' not set, using the default value: '%s'", defaultCommunity) 71 comm = defaultCommunity 72 } 73 74 switch ver { 75 case gosnmp.Version1: 76 client.SetCommunity(comm) 77 client.SetVersion(gosnmp.Version1) 78 case gosnmp.Version2c: 79 client.SetCommunity(comm) 80 client.SetVersion(gosnmp.Version2c) 81 case gosnmp.Version3: 82 client.SetVersion(gosnmp.Version3) 83 client.SetSecurityModel(gosnmp.UserSecurityModel) 84 client.SetMsgFlags(safeParseSNMPv3SecurityLevel(s.User.SecurityLevel)) 85 client.SetSecurityParameters(&gosnmp.UsmSecurityParameters{ 86 UserName: s.User.Name, 87 AuthenticationProtocol: safeParseSNMPv3AuthProtocol(s.User.AuthProto), 88 AuthenticationPassphrase: s.User.AuthKey, 89 PrivacyProtocol: safeParseSNMPv3PrivProtocol(s.User.PrivProto), 90 PrivacyPassphrase: s.User.PrivKey, 91 }) 92 default: 93 return nil, fmt.Errorf("invalid SNMP version: %s", s.Options.Version) 94 } 95 96 return client, nil 97 } 98 99 func (s SNMP) initOIDs() (oids []string) { 100 for _, c := range *s.charts { 101 for _, d := range c.Dims { 102 oids = append(oids, d.ID) 103 } 104 } 105 return oids 106 } 107 108 func parseSNMPVersion(version string) (gosnmp.SnmpVersion, error) { 109 switch version { 110 case "0", "1": 111 return gosnmp.Version1, nil 112 case "2", "2c", "": 113 return gosnmp.Version2c, nil 114 case "3": 115 return gosnmp.Version3, nil 116 default: 117 return gosnmp.Version2c, fmt.Errorf("invalid snmp version value (%s)", version) 118 } 119 } 120 121 func safeParseSNMPv3SecurityLevel(level string) gosnmp.SnmpV3MsgFlags { 122 v, _ := parseSNMPv3SecurityLevel(level) 123 return v 124 } 125 126 func parseSNMPv3SecurityLevel(level string) (gosnmp.SnmpV3MsgFlags, error) { 127 switch level { 128 case "1", "none", "noAuthNoPriv", "": 129 return gosnmp.NoAuthNoPriv, nil 130 case "2", "authNoPriv": 131 return gosnmp.AuthNoPriv, nil 132 case "3", "authPriv": 133 return gosnmp.AuthPriv, nil 134 default: 135 return gosnmp.NoAuthNoPriv, fmt.Errorf("invalid snmpv3 user security level value (%s)", level) 136 } 137 } 138 139 func safeParseSNMPv3AuthProtocol(protocol string) gosnmp.SnmpV3AuthProtocol { 140 v, _ := parseSNMPv3AuthProtocol(protocol) 141 return v 142 } 143 144 func parseSNMPv3AuthProtocol(protocol string) (gosnmp.SnmpV3AuthProtocol, error) { 145 switch protocol { 146 case "1", "none", "noAuth", "": 147 return gosnmp.NoAuth, nil 148 case "2", "md5": 149 return gosnmp.MD5, nil 150 case "3", "sha": 151 return gosnmp.SHA, nil 152 case "4", "sha224": 153 return gosnmp.SHA224, nil 154 case "5", "sha256": 155 return gosnmp.SHA256, nil 156 case "6", "sha384": 157 return gosnmp.SHA384, nil 158 case "7", "sha512": 159 return gosnmp.SHA512, nil 160 default: 161 return gosnmp.NoAuth, fmt.Errorf("invalid snmpv3 user auth protocol value (%s)", protocol) 162 } 163 } 164 165 func safeParseSNMPv3PrivProtocol(protocol string) gosnmp.SnmpV3PrivProtocol { 166 v, _ := parseSNMPv3PrivProtocol(protocol) 167 return v 168 } 169 170 func parseSNMPv3PrivProtocol(protocol string) (gosnmp.SnmpV3PrivProtocol, error) { 171 switch protocol { 172 case "1", "none", "noPriv", "": 173 return gosnmp.NoPriv, nil 174 case "2", "des": 175 return gosnmp.DES, nil 176 case "3", "aes": 177 return gosnmp.AES, nil 178 case "4", "aes192": 179 return gosnmp.AES192, nil 180 case "5", "aes256": 181 return gosnmp.AES256, nil 182 case "6", "aes192c": 183 return gosnmp.AES192C, nil 184 case "7", "aes256c": 185 return gosnmp.AES256C, nil 186 default: 187 return gosnmp.NoPriv, fmt.Errorf("invalid snmpv3 user priv protocol value (%s)", protocol) 188 } 189 }