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  }