This commit is contained in:
crusader 2018-08-30 21:56:32 +09:00
parent c28149db4b
commit 558e13da2e
6 changed files with 362 additions and 106 deletions

View File

@ -6,10 +6,11 @@ import (
omd "git.loafle.net/overflow/model/discovery" omd "git.loafle.net/overflow/model/discovery"
omu "git.loafle.net/overflow/model/util" omu "git.loafle.net/overflow/model/util"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/mdns"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/snmp"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/upnp"
"git.loafle.net/overflow_scanner/probe/discovery/session" "git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/discovery/types" "git.loafle.net/overflow_scanner/probe/discovery/types"
"git.loafle.net/overflow_scanner/probe/internal/protocol/mdns"
"git.loafle.net/overflow_scanner/probe/internal/protocol/upnp"
) )
type Discoverer interface { type Discoverer interface {
@ -47,21 +48,25 @@ type ofDiscoverer struct {
} }
func (d *ofDiscoverer) DiscoverHost(requesterID string, zone *omd.Zone, dh *omd.DiscoverHost) { func (d *ofDiscoverer) DiscoverHost(requesterID string, zone *omd.Zone, dh *omd.DiscoverHost) {
d.enqueue(retainDiscoveryRequest(d.messageChan, requesterID, types.DiscoveryRequestTypeHost, zone, dh)) d.enqueue(retainDiscoveryRequest(requesterID, types.DiscoveryRequestTypeHost, zone, dh))
} }
func (d *ofDiscoverer) DiscoverPort(requesterID string, host *omd.Host, dp *omd.DiscoverPort) { func (d *ofDiscoverer) DiscoverPort(requesterID string, host *omd.Host, dp *omd.DiscoverPort) {
d.enqueue(retainDiscoveryRequest(d.messageChan, requesterID, types.DiscoveryRequestTypePort, host, dp)) d.enqueue(retainDiscoveryRequest(requesterID, types.DiscoveryRequestTypePort, host, dp))
} }
func (d *ofDiscoverer) DiscoverService(requesterID string, port *omd.Port, ds *omd.DiscoverService) { func (d *ofDiscoverer) DiscoverService(requesterID string, port *omd.Port, ds *omd.DiscoverService) {
d.enqueue(retainDiscoveryRequest(d.messageChan, requesterID, types.DiscoveryRequestTypeService, port, ds)) d.enqueue(retainDiscoveryRequest(requesterID, types.DiscoveryRequestTypeService, port, ds))
} }
func (d *ofDiscoverer) Message() <-chan types.DiscoveryMessage { func (d *ofDiscoverer) Message() <-chan types.DiscoveryMessage {
return d.messageChan return d.messageChan
} }
func (d *ofDiscoverer) SendMessage(discoveryRequest types.DiscoveryRequest, messageType types.DiscoveryMessageType, data interface{}, err error) {
d.messageChan <- retainDiscoveryMessage(discoveryRequest, messageType, data, err)
}
func (d *ofDiscoverer) Shutdown() { func (d *ofDiscoverer) Shutdown() {
if d.stopChan == nil { if d.stopChan == nil {
return return
@ -89,18 +94,18 @@ func (d *ofDiscoverer) start() {
func (d *ofDiscoverer) enqueue(req *ofDiscoveryRequest) { func (d *ofDiscoverer) enqueue(req *ofDiscoveryRequest) {
select { select {
case d.requestQueue <- req: case d.requestQueue <- req:
req.SendMessage(types.DiscoveryMessageTypeQueueing, omu.Now(), nil) d.SendMessage(req, types.DiscoveryMessageTypeQueueing, omu.Now(), nil)
go func() { go func() {
select { select {
case <-req.dequeue: case <-req.dequeue:
case <-time.After(10 * time.Second): case <-time.After(10 * time.Second):
req.timeout = true req.timeout = true
req.SendMessage(types.DiscoveryMessageTypeTimeout, omu.Now(), nil) d.SendMessage(req, types.DiscoveryMessageTypeTimeout, omu.Now(), nil)
req.release() req.release()
} }
}() }()
default: default:
req.SendMessage(types.DiscoveryMessageTypeFailedQueueing, omu.Now(), nil) d.SendMessage(req, types.DiscoveryMessageTypeFailedQueueing, omu.Now(), nil)
req.release() req.release()
} }
} }
@ -122,9 +127,9 @@ LOOP:
} }
req.(*ofDiscoveryRequest).dequeue <- true req.(*ofDiscoveryRequest).dequeue <- true
req.SendMessage(types.DiscoveryMessageTypeStart, omu.Now(), nil) d.SendMessage(req, types.DiscoveryMessageTypeStart, omu.Now(), nil)
d.discover(req) d.discover(req)
req.SendMessage(types.DiscoveryMessageTypeStop, omu.Now(), nil) d.SendMessage(req, types.DiscoveryMessageTypeStop, omu.Now(), nil)
req.(*ofDiscoveryRequest).release() req.(*ofDiscoveryRequest).release()
case <-d.stopChan: case <-d.stopChan:
@ -144,17 +149,43 @@ func (d *ofDiscoverer) discover(req types.DiscoveryRequest) {
}() }()
if err := s.InitWithRequest(req); nil != err { if err := s.InitWithRequest(req); nil != err {
req.SendMessage(types.DiscoveryMessageTypeError, nil, err) d.SendMessage(req, types.DiscoveryMessageTypeError, nil, err)
return return
} }
d.preDiscovery(s) d.complexDiscover(s)
d.layerDiscovery(s) d.hierarchyDiscover(s)
} }
func (d *ofDiscoverer) preDiscovery(s session.DiscoverySession) { func (d *ofDiscoverer) complexDiscover(s session.DiscoverySession) {
var wg sync.WaitGroup var wg sync.WaitGroup
discoveredChan := make(chan interface{})
s.SetDiscoveryDelegator(discoveredChan)
defer func() {
s.SetDiscoveryDelegator(nil)
close(discoveredChan)
}()
go func() {
for {
select {
case target, ok := <-discoveredChan:
if !ok {
return
}
switch target.(type) {
case *omd.Host:
d.SendMessage(s.DiscoveryRequest(), types.DiscoveryMessageTypeHost, target, nil)
case *omd.Port:
d.SendMessage(s.DiscoveryRequest(), types.DiscoveryMessageTypePort, target, nil)
case *omd.Service:
d.SendMessage(s.DiscoveryRequest(), types.DiscoveryMessageTypeService, target, nil)
default:
}
}
}
}()
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
@ -167,11 +198,15 @@ func (d *ofDiscoverer) preDiscovery(s session.DiscoverySession) {
mdns.Scan(s) mdns.Scan(s)
}() }()
wg.Add(1)
go func() {
defer wg.Done()
snmp.Scan(s)
}()
wg.Wait() wg.Wait()
} }
func (d *ofDiscoverer) layerDiscovery(s session.DiscoverySession) { func (d *ofDiscoverer) hierarchyDiscover(s session.DiscoverySession) {
// SNMP
// mDNS
// UPnP
} }

View File

@ -11,9 +11,8 @@ type ofDiscoveryRequest struct {
requestType types.DiscoveryRequestType requestType types.DiscoveryRequestType
params []interface{} params []interface{}
messageChan chan<- types.DiscoveryMessage dequeue chan bool
dequeue chan bool timeout bool
timeout bool
} }
func (dr *ofDiscoveryRequest) RequesterID() string { func (dr *ofDiscoveryRequest) RequesterID() string {
@ -28,17 +27,13 @@ func (dr *ofDiscoveryRequest) Params() []interface{} {
return dr.params return dr.params
} }
func (dr *ofDiscoveryRequest) SendMessage(messageType types.DiscoveryMessageType, data interface{}, err error) {
dr.messageChan <- retainDiscoveryMessage(dr, messageType, data, err)
}
func (dr *ofDiscoveryRequest) release() { func (dr *ofDiscoveryRequest) release() {
releaseDiscoveryRequest(dr) releaseDiscoveryRequest(dr)
} }
var discoveryRequestPool sync.Pool var discoveryRequestPool sync.Pool
func retainDiscoveryRequest(messageChan chan<- types.DiscoveryMessage, requesterID string, requestType types.DiscoveryRequestType, params ...interface{}) *ofDiscoveryRequest { func retainDiscoveryRequest(requesterID string, requestType types.DiscoveryRequestType, params ...interface{}) *ofDiscoveryRequest {
v := discoveryRequestPool.Get() v := discoveryRequestPool.Get()
var dr *ofDiscoveryRequest var dr *ofDiscoveryRequest
if v == nil { if v == nil {
@ -50,7 +45,6 @@ func retainDiscoveryRequest(messageChan chan<- types.DiscoveryMessage, requester
dr.requesterID = requesterID dr.requesterID = requesterID
dr.requestType = requestType dr.requestType = requestType
dr.params = params dr.params = params
dr.messageChan = messageChan
dr.dequeue = make(chan bool, 1) dr.dequeue = make(chan bool, 1)
dr.timeout = false dr.timeout = false
@ -61,7 +55,6 @@ func releaseDiscoveryRequest(dr *ofDiscoveryRequest) {
dr.requesterID = "" dr.requesterID = ""
dr.requestType = types.DiscoveryRequestTypeNone dr.requestType = types.DiscoveryRequestTypeNone
dr.params = nil dr.params = nil
dr.messageChan = nil
close(dr.dequeue) close(dr.dequeue)
dr.dequeue = nil dr.dequeue = nil
dr.timeout = false dr.timeout = false

View File

@ -1,69 +1,141 @@
package snmp package snmp
import ( import (
"encoding/json"
"fmt" "fmt"
"net"
"strconv"
omcc "git.loafle.net/overflow/model/config/credential"
omd "git.loafle.net/overflow/model/discovery" omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
omu "git.loafle.net/overflow/model/util"
"git.loafle.net/overflow_scanner/probe/discovery/session"
"github.com/k-sone/snmpgo" "github.com/k-sone/snmpgo"
) )
var defaultPort = 161 const (
var defaultOIDs = []string{ defaultPort = 161
"1.3.6.1.2.1.1.5.0", //sysName defaultTimeout = 3
defaultCommunity = "public"
)
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)),
},
}
)
func Scan(discoverySession session.DiscoverySession) {
if nil == discoverySession.TargetHosts() || 0 == len(discoverySession.TargetHosts()) {
return
}
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)
}
_2cCS, ok := credentials["2c"]
if ok {
go func() {
LOOP:
for _, target := range discoverySession.TargetHosts() {
for _, c := range _2cCS {
if scanV2(target, discoverySession, c) {
continue LOOP
}
}
}
}()
}
} }
type SNMPResponse struct { func scanV2(target net.IP, discoverySession session.DiscoverySession, credential *omcc.SNMPCredential) bool {
Host *omd.Host
Value map[string]string
Error error
}
func ScanSNMP(host *omd.Host, community string, ch chan *SNMPResponse) { address := fmt.Sprintf("%s:%d", target.String(), credential.Port)
go func() {
getV2(host, defaultPort, community, defaultOIDs, ch)
}()
}
func getV2(host *omd.Host, port int, community string, _oids []string, ch chan *SNMPResponse) {
address := fmt.Sprintf("%s:%d", host.Address, port)
snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{ snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
Version: snmpgo.V2c, Version: snmpgo.V2c,
Address: address, Address: address,
Retries: 1, Retries: 1,
Community: community, Community: credential.Community,
}) })
if err != nil { if err != nil {
ch <- &SNMPResponse{host, nil, err} // ch <- &SNMPResponse{host, nil, err}
return return false
} }
defer snmp.Close() defer snmp.Close()
oids, err := snmpgo.NewOids(_oids) oids, err := snmpgo.NewOids(defaultOIDs)
if err != nil { if err != nil {
ch <- &SNMPResponse{host, nil, err} // ch <- &SNMPResponse{host, nil, err}
return return false
} }
pdu, err := snmp.GetRequest(oids) pdu, err := snmp.GetRequest(oids)
if err != nil { if err != nil {
ch <- &SNMPResponse{host, nil, err} // ch <- &SNMPResponse{host, nil, err}
return return false
} }
if pdu.ErrorStatus() != snmpgo.NoError { if pdu.ErrorStatus() != snmpgo.NoError {
ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())} // ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())}
return return false
} }
if pdu == nil { if pdu == nil {
ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")} // ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")}
return return false
} }
resMap := make(map[string]string) meta := make(map[string]string)
for _, val := range pdu.VarBinds() { for _, val := range pdu.VarBinds() {
resMap[val.Oid.String()] = val.Variable.String() meta[val.Oid.String()] = val.Variable.String()
} }
ch <- &SNMPResponse{host, resMap, nil}
return h := discoverySession.AddHost(&omd.Host{
MetaIPType: discoverySession.Zone().MetaIPType,
Name: "",
Address: target.String(),
Meta: meta,
Zone: discoverySession.Zone(),
DiscoveredDate: omu.NowPtr(),
})
p := discoverySession.AddPort(&omd.Port{
MetaPortType: omm.ToMetaPortType(omm.MetaPortTypeEnumUDP),
PortNumber: credential.Port,
Meta: meta,
Host: h,
})
discoverySession.AddService(&omd.Service{
MetaCryptoType: omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumNONE),
Key: "SNMP",
Name: "SNMP V2c",
Port: p,
})
return true
} }

View File

@ -3,21 +3,36 @@ package snmp
import ( import (
"testing" "testing"
omd "git.loafle.net/overflow/model/discovery" "git.loafle.net/overflow_scanner/probe/discovery"
omm "git.loafle.net/overflow/model/meta" "git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/discovery/types"
) )
func TestSNMPScan(t *testing.T) { func TestSNMPScan(t *testing.T) {
host := &omd.Host{ s := session.MockDiscoverySession()
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4), s.InitWithRequest(
Address: "192.168.1.229", discovery.MockDiscoveryRequest(
} "testRequester",
types.DiscoveryRequestTypeHost,
[]interface{}{
&omd.Zone{
Network: "192.168.1.0/24",
Iface: "enp3s0",
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
Address: "192.168.1.101",
Mac: "44:8a:5b:f1:f1:f3",
},
&omd.DiscoverHost{
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
FirstScanRange: "192.168.1.1",
LastScanRange: "192.168.1.254",
},
},
),
)
ch := make(chan *SNMPResponse) Scan(s)
defer close(ch)
ScanSNMP(host, "test1252serc", ch)
msg := <-ch
t.Log(msg) t.Log(msg)
} }

View File

@ -3,26 +3,36 @@ package session
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net"
"sync" "sync"
omd "git.loafle.net/overflow/model/discovery" omd "git.loafle.net/overflow/model/discovery"
ounc "git.loafle.net/overflow/util-go/net/cidr"
"git.loafle.net/overflow_scanner/probe/discovery/types" "git.loafle.net/overflow_scanner/probe/discovery/types"
) )
type DiscoverySession interface { type DiscoverySession interface {
InitWithRequest(request types.DiscoveryRequest) error
DiscoveryRequest() types.DiscoveryRequest
Zone() *omd.Zone Zone() *omd.Zone
Host() *omd.Host Host() *omd.Host
Port() *omd.Port Port() *omd.Port
DiscoveryConfig() *omd.DiscoveryConfig
DiscoverHost() *omd.DiscoverHost DiscoverHost() *omd.DiscoverHost
DiscoverPort() *omd.DiscoverPort DiscoverPort() *omd.DiscoverPort
DiscoverService() *omd.DiscoverService DiscoverService() *omd.DiscoverService
InitWithRequest(request types.DiscoveryRequest) error
AddHost(host *omd.Host) *omd.Host AddHost(host *omd.Host) *omd.Host
AddPort(port *omd.Port) *omd.Port AddPort(port *omd.Port) *omd.Port
AddService(service *omd.Service) *omd.Service AddService(service *omd.Service) *omd.Service
TargetHosts() []net.IP
SetDiscoveryDelegator(chan<- interface{})
} }
type ofDiscoverySession struct { type ofDiscoverySession struct {
@ -32,10 +42,16 @@ type ofDiscoverySession struct {
host *omd.Host host *omd.Host
port *omd.Port port *omd.Port
discoveryConfig *omd.DiscoveryConfig
discoverHost *omd.DiscoverHost discoverHost *omd.DiscoverHost
discoverPort *omd.DiscoverPort discoverPort *omd.DiscoverPort
discoverService *omd.DiscoverService discoverService *omd.DiscoverService
targetHosts []net.IP
discoveryDelegator chan<- interface{}
hosts map[string]*omd.Host hosts map[string]*omd.Host
ports map[*omd.Host]map[json.Number]map[string]*omd.Port ports map[*omd.Host]map[json.Number]map[string]*omd.Port
services map[*omd.Port]map[string]map[string]*omd.Service services map[*omd.Port]map[string]map[string]*omd.Service
@ -76,6 +92,17 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
return fmt.Errorf("DiscoverHost of parameter is not valid") return fmt.Errorf("DiscoverHost of parameter is not valid")
} }
if nil == discoverHost.DiscoveryConfig {
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
}
if ts, err := ds.getTargetHosts(zone, discoverHost); nil != err {
return err
} else {
ds.targetHosts = ts
}
ds.discoveryConfig = discoverHost.DiscoveryConfig
ds.setZone(zone) ds.setZone(zone)
ds.setDiscoverHost(discoverHost) ds.setDiscoverHost(discoverHost)
case types.DiscoveryRequestTypePort: case types.DiscoveryRequestTypePort:
@ -93,6 +120,11 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
return fmt.Errorf("DiscoverPort of parameter is not valid") return fmt.Errorf("DiscoverPort of parameter is not valid")
} }
if nil == discoverPort.DiscoveryConfig {
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
}
ds.discoveryConfig = discoverPort.DiscoveryConfig
ds.setHost(host) ds.setHost(host)
ds.setDiscoverPort(discoverPort) ds.setDiscoverPort(discoverPort)
case types.DiscoveryRequestTypeService: case types.DiscoveryRequestTypeService:
@ -110,6 +142,11 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
return fmt.Errorf("DiscoverService of parameter is not valid") return fmt.Errorf("DiscoverService of parameter is not valid")
} }
if nil == discoverService.DiscoveryConfig {
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
}
ds.discoveryConfig = discoverService.DiscoveryConfig
ds.setPort(port) ds.setPort(port)
ds.setDiscoverService(discoverService) ds.setDiscoverService(discoverService)
} }
@ -117,6 +154,14 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
return nil return nil
} }
func (ds *ofDiscoverySession) SetDiscoveryDelegator(discoveryDelegator chan<- interface{}) {
ds.discoveryDelegator = discoveryDelegator
}
func (ds *ofDiscoverySession) DiscoveryRequest() types.DiscoveryRequest {
return ds.discoveryRequest
}
func (ds *ofDiscoverySession) Zone() *omd.Zone { func (ds *ofDiscoverySession) Zone() *omd.Zone {
return ds.zone return ds.zone
} }
@ -127,6 +172,10 @@ func (ds *ofDiscoverySession) Port() *omd.Port {
return ds.port return ds.port
} }
func (ds *ofDiscoverySession) DiscoveryConfig() *omd.DiscoveryConfig {
return ds.discoveryConfig
}
func (ds *ofDiscoverySession) DiscoverHost() *omd.DiscoverHost { func (ds *ofDiscoverySession) DiscoverHost() *omd.DiscoverHost {
return ds.discoverHost return ds.discoverHost
} }
@ -137,59 +186,93 @@ func (ds *ofDiscoverySession) DiscoverService() *omd.DiscoverService {
return ds.discoverService return ds.discoverService
} }
func (ds *ofDiscoverySession) TargetHosts() []net.IP {
return ds.targetHosts
}
func (ds *ofDiscoverySession) AddHost(host *omd.Host) *omd.Host { func (ds *ofDiscoverySession) AddHost(host *omd.Host) *omd.Host {
h := ds.findHost(host, true) h, modified := ds.findHost(host, true)
if "" == h.Mac && "" != host.Mac { if "" == h.Mac && "" != host.Mac {
h.Mac = host.Mac h.Mac = host.Mac
modified = true
} }
h.Meta = ds.appendMeta(h.Meta, host.Meta) meta, metaModified := ds.appendMeta(h.Meta, host.Meta)
if metaModified {
h.Meta = meta
modified = metaModified
}
ds.discoveryRequest.SendMessage(types.DiscoveryMessageTypeHost, h, nil) if modified && nil != ds.discoveryDelegator {
ds.discoveryDelegator <- h
}
return h return h
} }
func (ds *ofDiscoverySession) AddPort(port *omd.Port) *omd.Port { func (ds *ofDiscoverySession) AddPort(port *omd.Port) *omd.Port {
p := ds.findPort(port, true) p, modified := ds.findPort(port, true)
p.Meta = ds.appendMeta(p.Meta, port.Meta) meta, metaModified := ds.appendMeta(p.Meta, port.Meta)
if metaModified {
p.Meta = meta
modified = metaModified
}
if modified && nil != ds.discoveryDelegator {
ds.discoveryDelegator <- p
}
return p return p
} }
func (ds *ofDiscoverySession) AddService(service *omd.Service) *omd.Service { func (ds *ofDiscoverySession) AddService(service *omd.Service) *omd.Service {
s := ds.findService(service, true) s, modified := ds.findService(service, true)
s.Meta = ds.appendMeta(s.Meta, service.Meta) meta, metaModified := ds.appendMeta(s.Meta, service.Meta)
if metaModified {
s.Meta = meta
modified = metaModified
}
if modified && nil != ds.discoveryDelegator {
ds.discoveryDelegator <- s
}
return s return s
} }
func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) *omd.Host { func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) (h *omd.Host, modified bool) {
h, ok := ds.hosts[host.Address] modified = false
var ok bool
h, ok = ds.hosts[host.Address]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
ds.hosts[host.Address] = host ds.hosts[host.Address] = host
h = host h = host
modified = true
} }
return h return
} }
func (ds *ofDiscoverySession) findPort(port *omd.Port, add bool) *omd.Port { func (ds *ofDiscoverySession) findPort(port *omd.Port, add bool) (p *omd.Port, modified bool) {
h := ds.findHost(port.Host, false) modified = false
var ok bool
h, _ := ds.findHost(port.Host, false)
if nil == h { if nil == h {
return nil return
} }
hostPorts, ok := ds.ports[h] hostPorts, ok := ds.ports[h]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
ds.ports[h] = make(map[json.Number]map[string]*omd.Port) ds.ports[h] = make(map[json.Number]map[string]*omd.Port)
@ -199,36 +282,40 @@ func (ds *ofDiscoverySession) findPort(port *omd.Port, add bool) *omd.Port {
ports, ok := hostPorts[port.PortNumber] ports, ok := hostPorts[port.PortNumber]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
hostPorts[port.PortNumber] = make(map[string]*omd.Port) hostPorts[port.PortNumber] = make(map[string]*omd.Port)
ports = hostPorts[port.PortNumber] ports = hostPorts[port.PortNumber]
} }
p, ok := ports[port.MetaPortType.Key] p, ok = ports[port.MetaPortType.Key]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
ports[port.MetaPortType.Key] = port ports[port.MetaPortType.Key] = port
p = ports[port.MetaPortType.Key] p = ports[port.MetaPortType.Key]
modified = true
} }
return p return
} }
func (ds *ofDiscoverySession) findService(service *omd.Service, add bool) *omd.Service { func (ds *ofDiscoverySession) findService(service *omd.Service, add bool) (s *omd.Service, modified bool) {
p := ds.findPort(service.Port, false) modified = false
var ok bool
p, _ := ds.findPort(service.Port, false)
if nil == p { if nil == p {
return nil return
} }
portServices, ok := ds.services[p] portServices, ok := ds.services[p]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
ds.services[p] = make(map[string]map[string]*omd.Service) ds.services[p] = make(map[string]map[string]*omd.Service)
@ -238,48 +325,57 @@ func (ds *ofDiscoverySession) findService(service *omd.Service, add bool) *omd.S
services, ok := portServices[service.Key] services, ok := portServices[service.Key]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
portServices[service.Key] = make(map[string]*omd.Service) portServices[service.Key] = make(map[string]*omd.Service)
services = portServices[service.Key] services = portServices[service.Key]
} }
s, ok := services[service.MetaCryptoType.Key] s, ok = services[service.MetaCryptoType.Key]
if !ok { if !ok {
if !add { if !add {
return nil return
} }
services[service.MetaCryptoType.Key] = service services[service.MetaCryptoType.Key] = service
s = services[service.MetaCryptoType.Key] s = services[service.MetaCryptoType.Key]
modified = true
} }
return s return
} }
func (ds *ofDiscoverySession) appendMeta(oriMeta map[string]string, newMeta map[string]string) map[string]string { func (ds *ofDiscoverySession) appendMeta(oriMeta map[string]string, newMeta map[string]string) (resultMap map[string]string, modified bool) {
modified = false
if nil == newMeta { if nil == newMeta {
return oriMeta resultMap = oriMeta
return
} }
if nil == oriMeta { if nil == oriMeta {
return newMeta resultMap = newMeta
modified = true
return
} }
LOOP: LOOP:
for k, v := range oriMeta { for k, v := range newMeta {
_v, _ok := oriMeta[k] _v, _ok := oriMeta[k]
if !_ok { if !_ok {
oriMeta[k] = v oriMeta[k] = v
modified = true
continue LOOP continue LOOP
} }
if v == _v { if v == _v {
continue LOOP continue LOOP
} }
oriMeta[k] = fmt.Sprintf("%s|||%s", _v, v) oriMeta[k] = fmt.Sprintf("%s|||%s", _v, v)
modified = true
} }
return oriMeta resultMap = oriMeta
return
} }
func (ds *ofDiscoverySession) setZone(zone *omd.Zone) { func (ds *ofDiscoverySession) setZone(zone *omd.Zone) {
@ -331,6 +427,53 @@ func (ds *ofDiscoverySession) setDiscoverService(discoverService *omd.DiscoverSe
ds.discoverService = discoverService ds.discoverService = discoverService
} }
func (ds *ofDiscoverySession) getTargetHosts(zone *omd.Zone, discoverHost *omd.DiscoverHost) ([]net.IP, error) {
cr, err := ounc.NewCIDRRanger(zone.Network)
if nil != err {
return nil, err
}
var firstIP net.IP
if "" != discoverHost.FirstScanRange {
firstIP = net.ParseIP(discoverHost.FirstScanRange)
if nil == firstIP {
return nil, fmt.Errorf("IP(%v) of FirstScanRange host is not valid", firstIP)
}
}
var lastIP net.IP
if "" != discoverHost.LastScanRange {
lastIP = net.ParseIP(discoverHost.LastScanRange)
if nil == lastIP {
return nil, fmt.Errorf("IP(%v) of LastScanRange host is not valid", lastIP)
}
}
includeIPs := make([]net.IP, 0)
for _, iHost := range discoverHost.IncludeHosts {
iIP := net.ParseIP(iHost)
if nil == iIP {
return nil, fmt.Errorf("IP(%v) of include host is not valid", iHost)
}
includeIPs = append(includeIPs, iIP)
}
excludeIPs := make([]net.IP, 0)
for _, eHost := range discoverHost.ExcludeHosts {
eIP := net.ParseIP(eHost)
if nil == eIP {
return nil, fmt.Errorf("IP(%v) of exclude host is not valid", eHost)
}
excludeIPs = append(excludeIPs, eIP)
}
ranges, err := cr.Ranges(firstIP, lastIP, includeIPs, excludeIPs)
if nil != err {
return nil, err
}
return ranges, nil
}
var discoverySessionPool sync.Pool var discoverySessionPool sync.Pool
func RetainDiscoverySession() *ofDiscoverySession { func RetainDiscoverySession() *ofDiscoverySession {

View File

@ -36,6 +36,4 @@ type DiscoveryRequest interface {
RequesterID() string RequesterID() string
RequestType() DiscoveryRequestType RequestType() DiscoveryRequestType
Params() []interface{} Params() []interface{}
SendMessage(messageType DiscoveryMessageType, data interface{}, err error)
} }