probe/discovery/session/discovery-session.go

1006 lines
21 KiB
Go
Raw Normal View History

2018-08-29 12:04:23 +00:00
package session
import (
"encoding/json"
"fmt"
2018-09-04 20:37:15 +00:00
"log"
2018-08-30 12:56:32 +00:00
"net"
2018-08-31 10:05:49 +00:00
"strconv"
2018-09-11 12:04:53 +00:00
"strings"
2018-08-29 12:04:23 +00:00
"sync"
2018-09-14 10:08:14 +00:00
"sync/atomic"
2018-08-29 12:04:23 +00:00
omd "git.loafle.net/overflow/model/discovery"
2018-09-13 10:20:58 +00:00
omm "git.loafle.net/overflow/model/meta"
omu "git.loafle.net/overflow/model/util"
2018-09-11 12:04:53 +00:00
ouej "git.loafle.net/overflow/util-go/encoding/json"
2018-08-30 12:56:32 +00:00
ounc "git.loafle.net/overflow/util-go/net/cidr"
2018-08-29 12:04:23 +00:00
"git.loafle.net/overflow_scanner/probe/discovery/types"
2018-09-04 18:58:33 +00:00
"git.loafle.net/overflow_scanner/probe/internal/pcap"
2018-08-29 12:04:23 +00:00
)
type DiscoverySession interface {
2018-08-30 12:56:32 +00:00
InitWithRequest(request types.DiscoveryRequest) error
DiscoveryRequest() types.DiscoveryRequest
2018-09-04 18:58:33 +00:00
PCapScanner() pcap.PCapScanner
2018-08-29 12:04:23 +00:00
Zone() *omd.Zone
Host() *omd.Host
Port() *omd.Port
2018-08-30 12:56:32 +00:00
DiscoveryConfig() *omd.DiscoveryConfig
2018-08-29 12:04:23 +00:00
DiscoverHost() *omd.DiscoverHost
DiscoverPort() *omd.DiscoverPort
DiscoverService() *omd.DiscoverService
2018-08-31 10:05:49 +00:00
TargetHosts() []net.IP
2018-09-13 11:05:03 +00:00
IsTargetHost(host *omd.Host) bool
IsTargetPort(port *omd.Port) bool
IsTargetService(service *omd.Service) bool
2018-08-31 10:05:49 +00:00
SetDiscoveryDelegator(chan<- interface{})
2018-09-11 07:59:21 +00:00
AddHost(discoveredBy string, host *omd.Host, meta map[string]string) *omd.Host
AddPort(discoveredBy string, port *omd.Port, meta map[string]string) *omd.Port
AddService(discoveredBy string, service *omd.Service, meta map[string]string) *omd.Service
2018-09-13 10:20:58 +00:00
AddServiceUnknown(discoveredBy string, port *omd.Port) *omd.Service
2018-08-30 12:56:32 +00:00
2018-08-31 10:05:49 +00:00
DiscoveredHost(address string) *omd.Host
2018-09-03 03:35:43 +00:00
DiscoveredAllHosts(includeMac bool) map[string]*omd.Host
2018-08-31 10:05:49 +00:00
DiscoveredPort(host *omd.Host, portNumber int) map[string]*omd.Port
2018-09-01 06:07:15 +00:00
DiscoveredAllPorts() map[*omd.Host]map[json.Number]map[string]*omd.Port
2018-09-13 10:20:58 +00:00
DiscoveredService(port *omd.Port, name string) *omd.Service
DiscoveredServices(port *omd.Port) map[string]*omd.Service
DiscoveredAllServices() map[*omd.Port]map[string]*omd.Service
2018-09-14 07:44:09 +00:00
Privileged() bool
2018-09-03 10:33:20 +00:00
2018-09-13 17:14:57 +00:00
Shutdown()
2018-09-03 10:33:20 +00:00
StopChan() <-chan struct{}
2018-08-29 12:04:23 +00:00
}
type ofDiscoverySession struct {
discoveryRequest types.DiscoveryRequest
2018-09-04 18:58:33 +00:00
pCapScanner pcap.PCapScanner
2018-08-29 12:04:23 +00:00
zone *omd.Zone
host *omd.Host
port *omd.Port
2018-08-30 12:56:32 +00:00
discoveryConfig *omd.DiscoveryConfig
2018-08-29 12:04:23 +00:00
discoverHost *omd.DiscoverHost
discoverPort *omd.DiscoverPort
discoverService *omd.DiscoverService
2018-09-13 11:45:17 +00:00
targetHosts []net.IP
targetHostAddresses map[string]bool
targetPortNumbers map[int]bool
2018-08-30 12:56:32 +00:00
discoveryDelegator chan<- interface{}
2018-09-03 05:24:30 +00:00
discoveredMtx sync.RWMutex
2018-09-03 03:35:43 +00:00
hosts map[string]*omd.Host
includeMachosts map[string]*omd.Host
ports map[*omd.Host]map[json.Number]map[string]*omd.Port
2018-09-13 10:20:58 +00:00
services map[*omd.Port]map[string]*omd.Service
2018-09-14 07:44:09 +00:00
privileged bool
2018-09-03 10:33:20 +00:00
2018-09-14 10:08:14 +00:00
stopped atomic.Value
2018-09-03 10:33:20 +00:00
stopChan chan struct{}
2018-08-29 12:04:23 +00:00
}
2018-08-29 18:20:51 +00:00
func (ds *ofDiscoverySession) init(request types.DiscoveryRequest) {
ds.discoveryRequest = request
2018-08-29 12:04:23 +00:00
ds.zone = nil
ds.host = nil
ds.port = nil
ds.discoverHost = nil
ds.discoverPort = nil
ds.discoverService = nil
2018-09-04 18:58:33 +00:00
ds.pCapScanner = nil
2018-08-29 12:04:23 +00:00
2018-09-13 11:45:17 +00:00
ds.targetHosts = nil
ds.targetHostAddresses = nil
ds.targetPortNumbers = nil
2018-08-29 12:04:23 +00:00
ds.hosts = make(map[string]*omd.Host)
2018-09-03 03:35:43 +00:00
ds.includeMachosts = make(map[string]*omd.Host)
2018-08-29 12:04:23 +00:00
ds.ports = make(map[*omd.Host]map[json.Number]map[string]*omd.Port)
2018-09-13 10:20:58 +00:00
ds.services = make(map[*omd.Port]map[string]*omd.Service)
2018-09-03 10:33:20 +00:00
2018-09-14 10:08:14 +00:00
ds.stopped.Store(false)
2018-09-03 10:33:20 +00:00
ds.stopChan = make(chan struct{})
2018-08-29 12:04:23 +00:00
}
2018-08-29 18:20:51 +00:00
func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) error {
ds.init(request)
params := request.Params()
switch request.RequestType() {
case types.DiscoveryRequestTypeHost:
if nil == params || 2 != len(params) {
return fmt.Errorf("Parameter is not valid")
}
zone, ok := params[0].(*omd.Zone)
if !ok {
return fmt.Errorf("Zone of parameter is not valid")
}
2018-09-13 11:45:17 +00:00
ds.setZone(zone)
2018-08-29 18:20:51 +00:00
discoverHost, ok := params[1].(*omd.DiscoverHost)
if !ok {
return fmt.Errorf("DiscoverHost of parameter is not valid")
}
2018-09-13 11:45:17 +00:00
if err := ds.setDiscoverHost(discoverHost); nil != err {
return err
}
2018-08-29 18:20:51 +00:00
2018-08-30 12:56:32 +00:00
if nil == discoverHost.DiscoveryConfig {
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
}
ds.discoveryConfig = discoverHost.DiscoveryConfig
2018-09-13 11:45:17 +00:00
2018-08-29 18:20:51 +00:00
case types.DiscoveryRequestTypePort:
if nil == params || 2 != len(params) {
return fmt.Errorf("Parameter is not valid")
}
host, ok := params[0].(*omd.Host)
if !ok {
return fmt.Errorf("Host of parameter is not valid")
}
2018-09-13 11:45:17 +00:00
ds.setHost(host)
2018-08-29 18:20:51 +00:00
discoverPort, ok := params[1].(*omd.DiscoverPort)
if !ok {
return fmt.Errorf("DiscoverPort of parameter is not valid")
}
2018-09-13 11:45:17 +00:00
if err := ds.setDiscoverPort(discoverPort); nil != err {
return err
}
2018-08-29 18:20:51 +00:00
2018-08-30 12:56:32 +00:00
if nil == discoverPort.DiscoveryConfig {
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
}
ds.discoveryConfig = discoverPort.DiscoveryConfig
2018-09-13 11:45:17 +00:00
2018-08-29 18:20:51 +00:00
case types.DiscoveryRequestTypeService:
if nil == params || 2 != len(params) {
return fmt.Errorf("Parameter is not valid")
}
port, ok := params[0].(*omd.Port)
if !ok {
return fmt.Errorf("Port of parameter is not valid")
}
2018-09-13 11:45:17 +00:00
ds.setPort(port)
2018-08-29 18:20:51 +00:00
discoverService, ok := params[1].(*omd.DiscoverService)
if !ok {
return fmt.Errorf("DiscoverService of parameter is not valid")
}
2018-09-13 11:45:17 +00:00
if err := ds.setDiscoverService(discoverService); nil != err {
return err
}
2018-08-29 18:20:51 +00:00
2018-08-30 12:56:32 +00:00
if nil == discoverService.DiscoveryConfig {
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
}
ds.discoveryConfig = discoverService.DiscoveryConfig
2018-08-29 18:20:51 +00:00
}
2018-09-04 18:58:33 +00:00
_pCapScanner := pcap.NewPCapScanner(ds.zone)
if err := _pCapScanner.Start(); nil == err {
ds.pCapScanner = _pCapScanner
2018-09-14 07:44:09 +00:00
ds.privileged = true
2018-09-04 20:37:15 +00:00
log.Print("Privileged mode")
} else {
2018-09-12 04:55:51 +00:00
log.Print(err)
2018-09-14 07:44:09 +00:00
ds.privileged = false
2018-09-04 20:37:15 +00:00
log.Print("Unprivileged mode")
2018-09-04 18:58:33 +00:00
}
2018-08-29 18:20:51 +00:00
return nil
2018-08-29 12:04:23 +00:00
}
2018-09-04 18:58:33 +00:00
func (ds *ofDiscoverySession) PCapScanner() pcap.PCapScanner {
return ds.pCapScanner
}
2018-09-14 07:44:09 +00:00
func (ds *ofDiscoverySession) Privileged() bool {
return ds.privileged
}
2018-08-30 12:56:32 +00:00
func (ds *ofDiscoverySession) SetDiscoveryDelegator(discoveryDelegator chan<- interface{}) {
ds.discoveryDelegator = discoveryDelegator
}
func (ds *ofDiscoverySession) DiscoveryRequest() types.DiscoveryRequest {
return ds.discoveryRequest
}
2018-08-29 12:04:23 +00:00
func (ds *ofDiscoverySession) Zone() *omd.Zone {
return ds.zone
}
func (ds *ofDiscoverySession) Host() *omd.Host {
return ds.host
}
func (ds *ofDiscoverySession) Port() *omd.Port {
return ds.port
}
2018-08-30 12:56:32 +00:00
func (ds *ofDiscoverySession) DiscoveryConfig() *omd.DiscoveryConfig {
return ds.discoveryConfig
}
2018-08-29 12:04:23 +00:00
func (ds *ofDiscoverySession) DiscoverHost() *omd.DiscoverHost {
return ds.discoverHost
}
func (ds *ofDiscoverySession) DiscoverPort() *omd.DiscoverPort {
return ds.discoverPort
}
func (ds *ofDiscoverySession) DiscoverService() *omd.DiscoverService {
return ds.discoverService
}
2018-08-30 12:56:32 +00:00
func (ds *ofDiscoverySession) TargetHosts() []net.IP {
return ds.targetHosts
}
2018-09-13 11:05:03 +00:00
func (ds *ofDiscoverySession) IsTargetHost(host *omd.Host) bool {
2018-09-13 11:45:17 +00:00
if nil == ds.targetHostAddresses {
return false
}
if _, ok := ds.targetHostAddresses[host.Address]; ok {
return true
2018-09-13 11:05:03 +00:00
}
2018-09-13 11:45:17 +00:00
2018-09-13 11:05:03 +00:00
return false
}
func (ds *ofDiscoverySession) IsTargetPort(port *omd.Port) bool {
2018-09-13 11:45:17 +00:00
if nil == ds.targetPortNumbers || 0 == len(ds.targetPortNumbers) {
2018-09-13 11:05:03 +00:00
return false
}
portNumber, err := ouej.NumberToInt(port.PortNumber)
if nil != err {
return false
}
if !ds.IsTargetHost(port.Host) {
return false
}
2018-09-13 11:45:17 +00:00
if _, ok := ds.targetPortNumbers[portNumber]; ok {
return true
2018-09-13 11:05:03 +00:00
}
2018-09-13 11:45:17 +00:00
return false
2018-09-13 11:05:03 +00:00
}
func (ds *ofDiscoverySession) IsTargetService(service *omd.Service) bool {
if nil == ds.discoverService {
return false
}
2018-09-13 11:45:17 +00:00
if !ds.IsTargetPort(service.Port) {
return false
}
2018-09-13 11:05:03 +00:00
return true
}
2018-09-11 07:59:21 +00:00
func (ds *ofDiscoverySession) AddHost(discoveredBy string, host *omd.Host, meta map[string]string) *omd.Host {
2018-09-03 05:24:30 +00:00
ds.discoveredMtx.Lock()
defer ds.discoveredMtx.Unlock()
2018-09-03 07:01:35 +00:00
h, modified := ds.findHost(host)
2018-08-29 12:04:23 +00:00
if "" == h.Mac && "" != host.Mac {
h.Mac = host.Mac
2018-08-30 12:56:32 +00:00
modified = true
2018-08-29 12:04:23 +00:00
}
2018-09-11 12:04:53 +00:00
if "" == h.OsType && "" != host.OsType {
h.OsType = host.OsType
modified = true
}
2018-09-12 04:55:51 +00:00
if omd.DefaultHostType == h.HostType && "" != host.HostType {
h.HostType = host.HostType
2018-09-11 12:04:53 +00:00
modified = true
}
2018-09-12 04:55:51 +00:00
if omd.DefaultHostVendor == h.HostVendor && "" != host.HostVendor {
h.HostVendor = host.HostVendor
2018-09-11 12:04:53 +00:00
modified = true
}
2018-09-12 04:55:51 +00:00
if omd.DefaultHostModel == h.HostModel && "" != host.HostModel {
h.HostModel = host.HostModel
2018-09-11 12:04:53 +00:00
modified = true
}
2018-09-11 07:59:21 +00:00
discoveredBys, discoveredByModified := ds.appendDiscoveredBy(discoveredBy, h.DiscoveredBy)
if discoveredByModified {
h.DiscoveredBy = discoveredBys
modified = true
}
metas, metaModified := ds.appendMeta(discoveredBy, h.Meta, meta)
2018-08-30 12:56:32 +00:00
if metaModified {
2018-09-11 07:59:21 +00:00
h.Meta = metas
modified = true
2018-08-30 12:56:32 +00:00
}
2018-08-29 12:04:23 +00:00
2018-09-11 12:04:53 +00:00
h, addtionalModified := ds.addtionalHost(discoveredBy, h)
if addtionalModified {
modified = true
}
if modified {
ds.delegate(h)
2018-08-30 12:56:32 +00:00
}
2018-08-29 12:04:23 +00:00
return h
}
2018-09-11 07:59:21 +00:00
func (ds *ofDiscoverySession) AddPort(discoveredBy string, port *omd.Port, meta map[string]string) *omd.Port {
2018-09-03 05:24:30 +00:00
ds.discoveredMtx.Lock()
defer ds.discoveredMtx.Unlock()
2018-09-03 07:01:35 +00:00
p, modified := ds.findPort(port)
2018-08-30 12:56:32 +00:00
2018-09-11 07:59:21 +00:00
discoveredBys, discoveredByModified := ds.appendDiscoveredBy(discoveredBy, p.DiscoveredBy)
if discoveredByModified {
p.DiscoveredBy = discoveredBys
modified = true
}
metas, metaModified := ds.appendMeta(discoveredBy, p.Meta, meta)
2018-08-30 12:56:32 +00:00
if metaModified {
2018-09-11 07:59:21 +00:00
p.Meta = metas
2018-08-30 12:56:32 +00:00
modified = metaModified
}
2018-08-29 12:04:23 +00:00
2018-09-11 12:04:53 +00:00
if modified {
ds.delegate(p)
2018-08-30 12:56:32 +00:00
}
2018-08-29 12:04:23 +00:00
return p
}
2018-09-11 07:59:21 +00:00
func (ds *ofDiscoverySession) AddService(discoveredBy string, service *omd.Service, meta map[string]string) *omd.Service {
2018-09-03 05:24:30 +00:00
ds.discoveredMtx.Lock()
defer ds.discoveredMtx.Unlock()
2018-09-03 07:01:35 +00:00
s, modified := ds.findService(service)
2018-08-29 12:04:23 +00:00
2018-09-12 04:55:51 +00:00
if omd.DefaultServiceType == s.ServiceType && "" != service.ServiceType {
s.ServiceType = service.ServiceType
modified = true
}
if omd.DefaultServiceVendor == s.ServiceVendor && "" != service.ServiceVendor {
s.ServiceVendor = service.ServiceVendor
modified = true
}
if omd.DefaultServiceVersion == s.ServiceVersion && "" != service.ServiceVersion {
s.ServiceVersion = service.ServiceVersion
modified = true
}
2018-09-11 07:59:21 +00:00
discoveredBys, discoveredByModified := ds.appendDiscoveredBy(discoveredBy, s.DiscoveredBy)
if discoveredByModified {
s.DiscoveredBy = discoveredBys
modified = true
}
metas, metaModified := ds.appendMeta(discoveredBy, s.Meta, meta)
2018-08-30 12:56:32 +00:00
if metaModified {
2018-09-11 07:59:21 +00:00
s.Meta = metas
2018-08-30 12:56:32 +00:00
modified = metaModified
}
2018-09-11 12:04:53 +00:00
s, addtionalModified := ds.addtionalService(discoveredBy, s)
if addtionalModified {
modified = true
}
if modified {
ds.delegate(s)
2018-08-30 12:56:32 +00:00
}
2018-08-29 12:04:23 +00:00
return s
}
2018-09-13 10:20:58 +00:00
func (ds *ofDiscoverySession) AddServiceUnknown(discoveredBy string, port *omd.Port) *omd.Service {
if nil == ds.DiscoveredServices(port) {
s := omd.NewService(
port,
omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumNONE),
omd.UnknownServiceKey,
)
s.Name = ""
s.ServiceType = omm.MetaServiceTypeEnumUNKNOWN.String()
s.ServiceVendor = ""
s.ServiceVersion = ""
s.DiscoveredDate = omu.NowPtr()
return ds.AddService(discoveredBy, s, nil)
}
return nil
}
2018-08-31 10:05:49 +00:00
func (ds *ofDiscoverySession) DiscoveredHost(address string) *omd.Host {
2018-09-03 05:24:30 +00:00
ds.discoveredMtx.RLock()
defer ds.discoveredMtx.RUnlock()
2018-08-31 10:05:49 +00:00
h, ok := ds.hosts[address]
if !ok {
return nil
}
return h
}
2018-09-03 03:35:43 +00:00
func (ds *ofDiscoverySession) DiscoveredAllHosts(includeMac bool) map[string]*omd.Host {
if includeMac {
return ds.includeMachosts
}
2018-09-01 06:07:15 +00:00
return ds.hosts
}
2018-08-31 10:05:49 +00:00
func (ds *ofDiscoverySession) DiscoveredPort(host *omd.Host, portNumber int) map[string]*omd.Port {
2018-09-03 05:24:30 +00:00
ds.discoveredMtx.RLock()
defer ds.discoveredMtx.RUnlock()
2018-09-03 07:01:35 +00:00
h, _ := ds.findHost(host)
2018-08-31 10:05:49 +00:00
if nil == h {
return nil
}
hostPorts, ok := ds.ports[h]
if !ok {
return nil
}
ports, ok := hostPorts[json.Number(strconv.Itoa(portNumber))]
if !ok {
return nil
}
return ports
}
2018-09-01 06:07:15 +00:00
func (ds *ofDiscoverySession) DiscoveredAllPorts() map[*omd.Host]map[json.Number]map[string]*omd.Port {
return ds.ports
}
2018-09-13 10:20:58 +00:00
func (ds *ofDiscoverySession) DiscoveredService(port *omd.Port, name string) *omd.Service {
2018-09-03 05:24:30 +00:00
ds.discoveredMtx.RLock()
defer ds.discoveredMtx.RUnlock()
2018-09-03 07:01:35 +00:00
p, _ := ds.findPort(port)
2018-08-31 10:05:49 +00:00
if nil == p {
return nil
}
2018-09-13 10:20:58 +00:00
services, ok := ds.services[p]
2018-08-31 10:05:49 +00:00
if !ok {
return nil
}
2018-09-13 10:20:58 +00:00
s, ok := services[name]
if !ok {
return nil
}
return s
}
func (ds *ofDiscoverySession) DiscoveredServices(port *omd.Port) map[string]*omd.Service {
ds.discoveredMtx.RLock()
defer ds.discoveredMtx.RUnlock()
p, _ := ds.findPort(port)
if nil == p {
return nil
}
services, ok := ds.services[p]
2018-08-31 10:05:49 +00:00
if !ok {
return nil
}
return services
}
2018-09-13 10:20:58 +00:00
func (ds *ofDiscoverySession) DiscoveredAllServices() map[*omd.Port]map[string]*omd.Service {
2018-09-01 06:07:15 +00:00
return ds.services
}
2018-09-11 12:04:53 +00:00
func (ds *ofDiscoverySession) StopChan() <-chan struct{} {
return ds.stopChan
}
func (ds *ofDiscoverySession) delegate(data interface{}) {
2018-09-14 10:08:14 +00:00
if true == ds.stopped.Load().(bool) {
return
}
2018-09-13 11:05:03 +00:00
switch v := data.(type) {
case *omd.Host:
if !ds.IsTargetHost(v) {
return
}
case *omd.Port:
if !ds.IsTargetPort(v) {
return
}
case *omd.Service:
if !ds.IsTargetService(v) {
return
}
default:
return
}
2018-09-11 12:04:53 +00:00
if nil != ds.discoveryDelegator {
ds.discoveryDelegator <- data
}
}
2018-09-13 17:14:57 +00:00
func (ds *ofDiscoverySession) Shutdown() {
2018-09-14 10:08:14 +00:00
ds.stopped.Store(true)
2018-09-13 17:14:57 +00:00
close(ds.stopChan)
}
2018-09-03 07:01:35 +00:00
func (ds *ofDiscoverySession) findHost(host *omd.Host) (h *omd.Host, modified bool) {
2018-08-30 12:56:32 +00:00
modified = false
var ok bool
2018-09-12 04:55:51 +00:00
if "" == host.HostType {
host.HostType = omd.DefaultHostType
2018-09-11 12:04:53 +00:00
}
if "" == host.OsType {
2018-09-12 04:55:51 +00:00
host.OsType = omd.DefaultOsType
2018-09-11 12:04:53 +00:00
}
2018-08-30 12:56:32 +00:00
h, ok = ds.hosts[host.Address]
2018-08-29 12:04:23 +00:00
if !ok {
ds.hosts[host.Address] = host
2018-09-03 03:35:43 +00:00
if "" != host.Mac {
ds.includeMachosts[host.Address] = host
}
2018-08-29 12:04:23 +00:00
h = host
2018-08-30 12:56:32 +00:00
modified = true
2018-08-29 12:04:23 +00:00
}
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
2018-09-03 07:01:35 +00:00
func (ds *ofDiscoverySession) findPort(port *omd.Port) (p *omd.Port, modified bool) {
2018-08-30 12:56:32 +00:00
modified = false
var ok bool
2018-09-03 07:01:35 +00:00
h, _ := ds.findHost(port.Host)
2018-08-29 12:04:23 +00:00
if nil == h {
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
hostPorts, ok := ds.ports[h]
if !ok {
ds.ports[h] = make(map[json.Number]map[string]*omd.Port)
hostPorts = ds.ports[h]
}
ports, ok := hostPorts[port.PortNumber]
if !ok {
hostPorts[port.PortNumber] = make(map[string]*omd.Port)
ports = hostPorts[port.PortNumber]
}
2018-08-30 12:56:32 +00:00
p, ok = ports[port.MetaPortType.Key]
2018-08-29 12:04:23 +00:00
if !ok {
ports[port.MetaPortType.Key] = port
p = ports[port.MetaPortType.Key]
2018-08-30 12:56:32 +00:00
modified = true
2018-08-29 12:04:23 +00:00
}
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
2018-09-03 07:01:35 +00:00
func (ds *ofDiscoverySession) findService(service *omd.Service) (s *omd.Service, modified bool) {
2018-08-30 12:56:32 +00:00
modified = false
var ok bool
2018-09-03 07:01:35 +00:00
p, _ := ds.findPort(service.Port)
2018-08-29 12:04:23 +00:00
if nil == p {
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
2018-09-13 10:20:58 +00:00
services, ok := ds.services[p]
2018-08-29 12:04:23 +00:00
if !ok {
2018-09-13 10:20:58 +00:00
ds.services[p] = make(map[string]*omd.Service)
services = ds.services[p]
} else {
if _, ok := services[omd.UnknownServiceKey]; ok {
delete(services, omd.UnknownServiceKey)
}
2018-08-29 12:04:23 +00:00
}
2018-09-13 10:20:58 +00:00
s, ok = services[service.Key]
2018-08-29 12:04:23 +00:00
if !ok {
2018-09-13 10:20:58 +00:00
services[service.Key] = service
s = services[service.Key]
2018-08-30 12:56:32 +00:00
modified = true
2018-08-29 12:04:23 +00:00
}
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
2018-09-11 12:04:53 +00:00
func (ds *ofDiscoverySession) addtionalHost(discoveredBy string, host *omd.Host) (h *omd.Host, modified bool) {
h = host
modified = false
if nil == host.Meta {
return
}
meta, ok := host.Meta[discoveredBy]
if !ok || nil == meta || 0 == len(meta) {
return
}
switch discoveredBy {
case "mDNS":
_h, _modified := ds.addtionalHostMDNS(h, meta)
if _modified {
h = _h
modified = true
}
}
return
}
func (ds *ofDiscoverySession) addtionalHostMDNS(host *omd.Host, meta map[string]string) (h *omd.Host, modified bool) {
h = host
modified = false
_vendor, ok := meta["vendor"]
if ok || "" != _vendor {
2018-09-12 04:55:51 +00:00
h.HostVendor = _vendor
2018-09-11 12:04:53 +00:00
modified = true
}
_model, ok := meta["model"]
if ok || "" != _model {
2018-09-12 04:55:51 +00:00
h.HostModel = _model
2018-09-11 12:04:53 +00:00
if "Synology" == _vendor && strings.Contains(_model, "DS1817+") {
2018-09-12 04:55:51 +00:00
h.HostType = "NAS"
2018-09-11 12:04:53 +00:00
}
modified = true
}
return
}
func (ds *ofDiscoverySession) addtionalService(discoveredBy string, service *omd.Service) (s *omd.Service, modified bool) {
s = service
modified = false
if nil == service.Meta {
return
}
meta, ok := service.Meta[discoveredBy]
if !ok || nil == meta || 0 == len(meta) {
return
}
switch discoveredBy {
case "mDNS":
_s, _modified := ds.addtionalServiceMDNS(s, meta)
if _modified {
s = _s
modified = true
}
}
return
}
func (ds *ofDiscoverySession) addtionalServiceMDNS(service *omd.Service, meta map[string]string) (s *omd.Service, modified bool) {
s = service
modified = false
portNumber, err := ouej.NumberToInt(service.Port.PortNumber)
if nil != err {
log.Print(err)
return
}
switch portNumber {
case 515:
if "printer" == service.Key {
_h := service.Port.Host
2018-09-12 04:55:51 +00:00
_h.HostType = "PRINTER"
2018-09-11 12:04:53 +00:00
_h.Name = service.Name
2018-09-12 04:55:51 +00:00
ds.delegate(_h)
2018-09-11 12:04:53 +00:00
}
case 9100:
if "pdl-datastream" == service.Key {
_h := service.Port.Host
2018-09-12 04:55:51 +00:00
_h.HostType = "PRINTER"
2018-09-11 12:04:53 +00:00
_h.Name = service.Name
2018-09-12 04:55:51 +00:00
ds.delegate(_h)
2018-09-11 12:04:53 +00:00
}
}
return
}
2018-09-11 07:59:21 +00:00
func (ds *ofDiscoverySession) appendDiscoveredBy(discoveredBy string, oriDiscoveredBy []string) (resultDiscoveredBy []string, modified bool) {
modified = false
if "" == discoveredBy {
resultDiscoveredBy = oriDiscoveredBy
return
}
if nil == oriDiscoveredBy {
resultDiscoveredBy = []string{
discoveredBy,
}
modified = true
return
}
for _, v := range oriDiscoveredBy {
if v == discoveredBy {
resultDiscoveredBy = oriDiscoveredBy
return
}
}
oriDiscoveredBy = append(oriDiscoveredBy, discoveredBy)
resultDiscoveredBy = oriDiscoveredBy
modified = true
return
}
func (ds *ofDiscoverySession) appendMeta(discoveredBy string, oriMetas map[string]map[string]string, newMeta map[string]string) (resultMetas map[string]map[string]string, modified bool) {
2018-08-30 12:56:32 +00:00
modified = false
2018-09-11 07:59:21 +00:00
if nil == newMeta || 0 == len(newMeta) {
resultMetas = oriMetas
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
2018-09-11 07:59:21 +00:00
if nil == oriMetas {
resultMetas = map[string]map[string]string{
discoveredBy: newMeta,
}
2018-08-30 12:56:32 +00:00
modified = true
return
2018-08-29 12:04:23 +00:00
}
2018-09-11 07:59:21 +00:00
oriMeta, ok := oriMetas[discoveredBy]
if !ok {
oriMetas[discoveredBy] = newMeta
resultMetas = oriMetas
return
}
2018-08-29 12:04:23 +00:00
LOOP:
2018-08-30 12:56:32 +00:00
for k, v := range newMeta {
2018-08-29 12:04:23 +00:00
_v, _ok := oriMeta[k]
if !_ok {
oriMeta[k] = v
2018-08-30 12:56:32 +00:00
modified = true
2018-08-29 12:04:23 +00:00
continue LOOP
}
if v == _v {
continue LOOP
}
oriMeta[k] = fmt.Sprintf("%s|||%s", _v, v)
2018-08-30 12:56:32 +00:00
modified = true
2018-08-29 12:04:23 +00:00
}
2018-09-11 07:59:21 +00:00
resultMetas = oriMetas
2018-08-30 12:56:32 +00:00
return
2018-08-29 12:04:23 +00:00
}
func (ds *ofDiscoverySession) setZone(zone *omd.Zone) {
if nil == zone {
return
}
ds.zone = zone
}
func (ds *ofDiscoverySession) setHost(host *omd.Host) {
if nil == host {
return
}
ds.setZone(host.Zone)
ds.host = host
}
func (ds *ofDiscoverySession) setPort(port *omd.Port) {
if nil == port {
return
}
ds.setHost(port.Host)
ds.port = port
}
2018-09-13 11:45:17 +00:00
func (ds *ofDiscoverySession) setDiscoverHost(discoverHost *omd.DiscoverHost) error {
2018-08-29 12:04:23 +00:00
if nil == discoverHost {
2018-09-13 11:45:17 +00:00
return nil
}
if err := ds.setTargetHosts(ds.zone, discoverHost); nil != err {
return err
2018-08-29 12:04:23 +00:00
}
ds.discoverHost = discoverHost
2018-09-13 11:45:17 +00:00
return ds.setDiscoverPort(discoverHost.DiscoverPort)
2018-08-29 12:04:23 +00:00
}
2018-09-13 11:45:17 +00:00
func (ds *ofDiscoverySession) setDiscoverPort(discoverPort *omd.DiscoverPort) error {
2018-08-29 12:04:23 +00:00
if nil == discoverPort {
2018-09-13 11:45:17 +00:00
return nil
}
if err := ds.setTargetPortNumbers(discoverPort); nil != err {
return err
2018-08-29 12:04:23 +00:00
}
ds.discoverPort = discoverPort
2018-09-13 11:45:17 +00:00
return ds.setDiscoverService(discoverPort.DiscoverService)
2018-08-29 12:04:23 +00:00
}
2018-09-13 11:45:17 +00:00
func (ds *ofDiscoverySession) setDiscoverService(discoverService *omd.DiscoverService) error {
2018-08-29 12:04:23 +00:00
if nil == discoverService {
2018-09-13 11:45:17 +00:00
return nil
2018-08-29 12:04:23 +00:00
}
ds.discoverService = discoverService
2018-09-13 11:45:17 +00:00
return nil
2018-08-29 12:04:23 +00:00
}
2018-09-13 11:45:17 +00:00
func (ds *ofDiscoverySession) setTargetHosts(zone *omd.Zone, discoverHost *omd.DiscoverHost) error {
2018-08-30 12:56:32 +00:00
cr, err := ounc.NewCIDRRanger(zone.Network)
if nil != err {
2018-09-13 11:45:17 +00:00
return err
2018-08-30 12:56:32 +00:00
}
var firstIP net.IP
if "" != discoverHost.FirstScanRange {
firstIP = net.ParseIP(discoverHost.FirstScanRange)
if nil == firstIP {
2018-09-13 11:45:17 +00:00
return fmt.Errorf("IP(%v) of FirstScanRange host is not valid", firstIP)
2018-08-30 12:56:32 +00:00
}
}
var lastIP net.IP
if "" != discoverHost.LastScanRange {
lastIP = net.ParseIP(discoverHost.LastScanRange)
if nil == lastIP {
2018-09-13 11:45:17 +00:00
return fmt.Errorf("IP(%v) of LastScanRange host is not valid", lastIP)
2018-08-30 12:56:32 +00:00
}
}
includeIPs := make([]net.IP, 0)
for _, iHost := range discoverHost.IncludeHosts {
iIP := net.ParseIP(iHost)
if nil == iIP {
2018-09-13 11:45:17 +00:00
return fmt.Errorf("IP(%v) of include host is not valid", iHost)
2018-08-30 12:56:32 +00:00
}
includeIPs = append(includeIPs, iIP)
}
excludeIPs := make([]net.IP, 0)
for _, eHost := range discoverHost.ExcludeHosts {
eIP := net.ParseIP(eHost)
if nil == eIP {
2018-09-13 11:45:17 +00:00
return fmt.Errorf("IP(%v) of exclude host is not valid", eHost)
2018-08-30 12:56:32 +00:00
}
excludeIPs = append(excludeIPs, eIP)
}
ranges, err := cr.Ranges(firstIP, lastIP, includeIPs, excludeIPs)
if nil != err {
2018-09-13 11:45:17 +00:00
return err
2018-08-30 12:56:32 +00:00
}
2018-09-13 11:45:17 +00:00
ds.targetHosts = ranges
ds.targetHostAddresses = make(map[string]bool, len(ranges))
for _, ip := range ranges {
ds.targetHostAddresses[ip.String()] = true
}
return nil
}
func (ds *ofDiscoverySession) setTargetPortNumbers(discoverPort *omd.DiscoverPort) error {
if nil == discoverPort {
return nil
}
ds.targetPortNumbers = make(map[int]bool, 0)
LOOP:
for portNumber := discoverPort.FirstScanRange; portNumber < discoverPort.LastScanRange; portNumber++ {
if nil != discoverPort.ExcludePorts {
for _, exPortNumber := range discoverPort.ExcludePorts {
if portNumber == exPortNumber {
continue LOOP
}
}
}
ds.targetPortNumbers[portNumber] = true
}
return nil
2018-08-30 12:56:32 +00:00
}
2018-08-29 12:04:23 +00:00
var discoverySessionPool sync.Pool
func RetainDiscoverySession() *ofDiscoverySession {
v := discoverySessionPool.Get()
var ds *ofDiscoverySession
if v == nil {
ds = &ofDiscoverySession{}
} else {
ds = v.(*ofDiscoverySession)
}
return ds
}
func ReleaseDiscoverySession(ds *ofDiscoverySession) {
2018-09-14 10:08:14 +00:00
ds.stopChan = nil
2018-09-03 10:33:20 +00:00
2018-09-04 18:58:33 +00:00
if nil != ds.pCapScanner {
ds.pCapScanner.Stop()
}
2018-09-04 10:09:15 +00:00
2018-09-04 18:58:33 +00:00
ds.pCapScanner = nil
2018-08-29 12:04:23 +00:00
ds.discoveryRequest = nil
ds.zone = nil
ds.host = nil
ds.port = nil
2018-09-04 18:58:33 +00:00
ds.discoveryConfig = nil
2018-08-29 12:04:23 +00:00
ds.discoverHost = nil
ds.discoverPort = nil
ds.discoverService = nil
2018-09-04 18:58:33 +00:00
ds.targetHosts = nil
2018-09-13 11:45:17 +00:00
ds.targetHostAddresses = nil
ds.targetPortNumbers = nil
2018-09-04 18:58:33 +00:00
ds.discoveryDelegator = nil
2018-09-03 10:33:20 +00:00
ds.includeMachosts = nil
2018-08-29 12:04:23 +00:00
ds.hosts = nil
ds.ports = nil
ds.services = nil
discoverySessionPool.Put(ds)
}