probe/discovery/protocol/snmp/snmp.go

190 lines
3.7 KiB
Go
Raw Normal View History

2018-08-29 12:04:23 +00:00
package snmp
import (
2018-08-30 12:56:32 +00:00
"encoding/json"
2018-09-12 04:55:51 +00:00
"log"
2018-08-30 12:56:32 +00:00
"net"
"strconv"
2018-08-31 02:32:25 +00:00
"sync"
"time"
2018-08-29 12:04:23 +00:00
2018-08-30 12:56:32 +00:00
omcc "git.loafle.net/overflow/model/config/credential"
2018-08-29 12:04:23 +00:00
omd "git.loafle.net/overflow/model/discovery"
2018-08-30 12:56:32 +00:00
omm "git.loafle.net/overflow/model/meta"
omu "git.loafle.net/overflow/model/util"
2018-09-12 04:55:51 +00:00
ouej "git.loafle.net/overflow/util-go/encoding/json"
2018-08-30 12:56:32 +00:00
"git.loafle.net/overflow_scanner/probe/discovery/session"
2018-08-29 12:04:23 +00:00
"github.com/k-sone/snmpgo"
)
2018-08-30 12:56:32 +00:00
const (
defaultPort = 161
2018-08-31 02:32:25 +00:00
defaultTimeout = 1
2018-08-30 12:56:32 +00:00
defaultCommunity = "public"
)
2018-08-29 12:04:23 +00:00
2018-08-30 12:56:32 +00:00
var (
defaultOIDs = []string{
"1.3.6.1.2.1.1.5.0", //sysName
}
defaultCredentials = []*omcc.SNMPCredential{
&omcc.SNMPCredential{
Version: "2c",
Community: "public",
Port: json.Number(strconv.Itoa(defaultPort)),
Timeout: json.Number(strconv.Itoa(defaultTimeout)),
},
}
)
2018-08-31 05:15:46 +00:00
func Scan(discoverySession session.DiscoverySession) error {
2018-08-31 02:32:25 +00:00
targetHosts := discoverySession.TargetHosts()
if nil == targetHosts || 0 == len(targetHosts) {
2018-08-31 05:15:46 +00:00
return nil
2018-08-30 12:56:32 +00:00
}
var cs []*omcc.SNMPCredential
if _csMap := discoverySession.DiscoveryConfig().Credentials; nil != _csMap {
_cs, ok := _csMap["SNMP"]
if ok {
cs = _cs.([]*omcc.SNMPCredential)
}
}
if nil == cs {
cs = defaultCredentials
}
credentials := make(map[string][]*omcc.SNMPCredential)
for _, _c := range cs {
credentials[_c.Version] = append(credentials[_c.Version], _c)
}
2018-08-29 12:04:23 +00:00
2018-08-31 02:32:25 +00:00
var wg sync.WaitGroup
2018-08-30 12:56:32 +00:00
_2cCS, ok := credentials["2c"]
if ok {
2018-08-31 02:32:25 +00:00
wg.Add(1)
2018-08-30 12:56:32 +00:00
go func() {
2018-08-31 02:32:25 +00:00
defer wg.Done()
2018-08-31 04:05:59 +00:00
2018-08-31 02:32:25 +00:00
for _, target := range targetHosts {
2018-08-31 04:05:59 +00:00
wg.Add(1)
go func(target net.IP) {
defer wg.Done()
for _, c := range _2cCS {
if scanV2(target, discoverySession, c) {
return
}
2018-08-30 12:56:32 +00:00
}
2018-08-31 04:05:59 +00:00
}(target)
2018-09-03 10:33:20 +00:00
select {
case <-discoverySession.StopChan():
return
default:
}
2018-08-30 12:56:32 +00:00
}
}()
}
2018-08-31 02:32:25 +00:00
wg.Wait()
2018-08-31 05:15:46 +00:00
return nil
2018-08-29 12:04:23 +00:00
}
2018-08-30 12:56:32 +00:00
func scanV2(target net.IP, discoverySession session.DiscoverySession, credential *omcc.SNMPCredential) bool {
2018-09-12 04:55:51 +00:00
portNumber, err := ouej.NumberToInt(credential.Port)
if nil != err {
log.Print(err)
return false
}
address := net.JoinHostPort(target.String(), credential.Port.String())
2018-08-31 02:32:25 +00:00
timeout, _ := credential.Timeout.Int64()
2018-08-29 12:04:23 +00:00
snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
Version: snmpgo.V2c,
Address: address,
2018-08-31 02:32:25 +00:00
Timeout: time.Second * time.Duration(timeout),
2018-08-29 12:04:23 +00:00
Retries: 1,
2018-08-30 12:56:32 +00:00
Community: credential.Community,
2018-08-29 12:04:23 +00:00
})
2018-08-31 02:32:25 +00:00
2018-08-29 12:04:23 +00:00
if err != nil {
2018-08-30 12:56:32 +00:00
// ch <- &SNMPResponse{host, nil, err}
return false
2018-08-29 12:04:23 +00:00
}
defer snmp.Close()
2018-08-30 12:56:32 +00:00
oids, err := snmpgo.NewOids(defaultOIDs)
2018-08-29 12:04:23 +00:00
if err != nil {
2018-08-30 12:56:32 +00:00
// ch <- &SNMPResponse{host, nil, err}
return false
2018-08-29 12:04:23 +00:00
}
pdu, err := snmp.GetRequest(oids)
if err != nil {
2018-08-30 12:56:32 +00:00
// ch <- &SNMPResponse{host, nil, err}
return false
2018-08-29 12:04:23 +00:00
}
if pdu.ErrorStatus() != snmpgo.NoError {
2018-08-30 12:56:32 +00:00
// ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())}
return false
2018-08-29 12:04:23 +00:00
}
if pdu == nil {
2018-08-30 12:56:32 +00:00
// ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")}
return false
2018-08-29 12:04:23 +00:00
}
2018-08-30 12:56:32 +00:00
meta := make(map[string]string)
2018-08-29 12:04:23 +00:00
for _, val := range pdu.VarBinds() {
2018-08-30 12:56:32 +00:00
meta[val.Oid.String()] = val.Variable.String()
2018-08-29 12:04:23 +00:00
}
2018-08-30 12:56:32 +00:00
2018-09-12 04:55:51 +00:00
h := omd.NewHost(
discoverySession.Zone(),
discoverySession.Zone().MetaIPType,
target.String(),
)
h.DiscoveredDate = omu.NowPtr()
h = discoverySession.AddHost(
2018-09-11 07:59:21 +00:00
"SNMP V2c",
2018-09-12 04:55:51 +00:00
h,
2018-09-11 07:59:21 +00:00
meta,
)
2018-09-12 04:55:51 +00:00
p := omd.NewPort(
h,
omm.ToMetaPortType(omm.MetaPortTypeEnumUDP),
portNumber,
2018-09-11 07:59:21 +00:00
)
2018-09-12 04:55:51 +00:00
p.DiscoveredDate = omu.NowPtr()
2018-09-11 07:59:21 +00:00
2018-09-12 04:55:51 +00:00
p = discoverySession.AddPort(
"SNMP V2c",
p,
2018-09-11 07:59:21 +00:00
meta,
)
2018-08-30 12:56:32 +00:00
2018-09-12 04:55:51 +00:00
s := omd.NewService(
p,
omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumNONE),
"SNMP",
)
s.Name = "SNMP V2c"
s.ServiceType = omm.MetaServiceTypeEnumMonitoring.String()
s.ServiceVersion = "2c"
s.DiscoveredDate = omu.NowPtr()
discoverySession.AddService(
"SNMP V2c",
s,
meta,
)
2018-09-01 02:19:03 +00:00
2018-08-30 12:56:32 +00:00
return true
2018-08-29 12:04:23 +00:00
}