1101 lines
24 KiB
Go
1101 lines
24 KiB
Go
package session
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
omd "git.loafle.net/overflow/model/discovery"
|
|
omm "git.loafle.net/overflow/model/meta"
|
|
omu "git.loafle.net/overflow/model/util"
|
|
ouej "git.loafle.net/overflow/util-go/encoding/json"
|
|
ounc "git.loafle.net/overflow/util-go/net/cidr"
|
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
|
"git.loafle.net/overflow_scanner/probe/internal/pcap"
|
|
"github.com/google/gopacket/layers"
|
|
)
|
|
|
|
const (
|
|
MetaSeperator = "|||"
|
|
)
|
|
|
|
type DiscoverySession interface {
|
|
InitWithRequest(request types.DiscoveryRequest) error
|
|
|
|
DiscoveryRequest() types.DiscoveryRequest
|
|
|
|
PCapScanner() pcap.PCapScanner
|
|
|
|
Zone() *omd.Zone
|
|
Host() *omd.Host
|
|
Port() *omd.Port
|
|
|
|
DiscoveryConfig() *omd.DiscoveryConfig
|
|
|
|
DiscoverHost() *omd.DiscoverHost
|
|
DiscoverPort() *omd.DiscoverPort
|
|
DiscoverService() *omd.DiscoverService
|
|
|
|
TargetHosts() []net.IP
|
|
IsTargetHost(host *omd.Host) bool
|
|
IsTargetPort(port *omd.Port) bool
|
|
IsTargetService(service *omd.Service) bool
|
|
|
|
HostNeedScan(host *omd.Host, discovererType *omm.MetaDiscovererType) bool
|
|
|
|
SetDiscoveryDelegator(chan<- interface{})
|
|
|
|
AddHost(discoveredBy *omm.MetaDiscovererType, host *omd.Host, meta map[string]string) *omd.Host
|
|
AddPort(discoveredBy *omm.MetaDiscovererType, port *omd.Port, meta map[string]string) *omd.Port
|
|
AddService(discoveredBy *omm.MetaDiscovererType, service *omd.Service, meta map[string]string) *omd.Service
|
|
AddServiceUnknown(discoveredBy *omm.MetaDiscovererType, port *omd.Port) *omd.Service
|
|
|
|
DiscoveredHost(address string) *omd.Host
|
|
DiscoveredAllHosts(includeMac bool) map[string]*omd.Host
|
|
DiscoveredPort(host *omd.Host, portNumber int) map[string]*omd.Port
|
|
DiscoveredAllPorts() map[*omd.Host]map[json.Number]map[string]*omd.Port
|
|
DiscoveredService(port *omd.Port, name string) *omd.Service
|
|
DiscoveredServices(port *omd.Port) map[string]*omd.Service
|
|
DiscoveredAllServices() map[*omd.Port]map[string]*omd.Service
|
|
Privileged() bool
|
|
|
|
Shutdown()
|
|
StopChan() <-chan struct{}
|
|
}
|
|
|
|
type ofDiscoverySession struct {
|
|
discoveryRequest types.DiscoveryRequest
|
|
pCapScanner pcap.PCapScanner
|
|
|
|
zone *omd.Zone
|
|
host *omd.Host
|
|
port *omd.Port
|
|
|
|
discoveryConfig *omd.DiscoveryConfig
|
|
|
|
discoverHost *omd.DiscoverHost
|
|
discoverPort *omd.DiscoverPort
|
|
discoverService *omd.DiscoverService
|
|
|
|
targetHosts []net.IP
|
|
targetHostAddresses map[string]bool
|
|
targetPortNumbers map[int]bool
|
|
|
|
discoveryDelegator chan<- interface{}
|
|
|
|
discoveredMtx sync.RWMutex
|
|
hosts map[string]*omd.Host
|
|
includeMacHosts map[string]*omd.Host
|
|
ports map[*omd.Host]map[json.Number]map[string]*omd.Port
|
|
services map[*omd.Port]map[string]*omd.Service
|
|
privileged bool
|
|
|
|
hostScanned map[string]map[string]bool
|
|
hostScannedMtx sync.Mutex
|
|
|
|
stopped atomic.Value
|
|
stopChan chan struct{}
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) init(request types.DiscoveryRequest) {
|
|
ds.discoveryRequest = request
|
|
ds.zone = nil
|
|
ds.host = nil
|
|
ds.port = nil
|
|
ds.discoverHost = nil
|
|
ds.discoverPort = nil
|
|
ds.discoverService = nil
|
|
ds.pCapScanner = nil
|
|
|
|
ds.targetHosts = nil
|
|
ds.targetHostAddresses = nil
|
|
ds.targetPortNumbers = nil
|
|
ds.hosts = make(map[string]*omd.Host)
|
|
ds.includeMacHosts = make(map[string]*omd.Host)
|
|
ds.ports = make(map[*omd.Host]map[json.Number]map[string]*omd.Port)
|
|
ds.services = make(map[*omd.Port]map[string]*omd.Service)
|
|
ds.hostScanned = make(map[string]map[string]bool)
|
|
|
|
ds.stopped.Store(false)
|
|
ds.stopChan = make(chan struct{})
|
|
}
|
|
|
|
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")
|
|
}
|
|
ds.setZone(zone)
|
|
|
|
discoverHost, ok := params[1].(*omd.DiscoverHost)
|
|
if !ok {
|
|
return fmt.Errorf("DiscoverHost of parameter is not valid")
|
|
}
|
|
if err := ds.setDiscoverHost(discoverHost); nil != err {
|
|
return err
|
|
}
|
|
|
|
if nil == discoverHost.DiscoveryConfig {
|
|
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
|
|
}
|
|
ds.discoveryConfig = discoverHost.DiscoveryConfig
|
|
|
|
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")
|
|
}
|
|
ds.setHost(host)
|
|
|
|
discoverPort, ok := params[1].(*omd.DiscoverPort)
|
|
if !ok {
|
|
return fmt.Errorf("DiscoverPort of parameter is not valid")
|
|
}
|
|
if err := ds.setDiscoverPort(discoverPort); nil != err {
|
|
return err
|
|
}
|
|
|
|
if nil == discoverPort.DiscoveryConfig {
|
|
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
|
|
}
|
|
ds.discoveryConfig = discoverPort.DiscoveryConfig
|
|
|
|
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")
|
|
}
|
|
ds.setPort(port)
|
|
|
|
discoverService, ok := params[1].(*omd.DiscoverService)
|
|
if !ok {
|
|
return fmt.Errorf("DiscoverService of parameter is not valid")
|
|
}
|
|
if err := ds.setDiscoverService(discoverService); nil != err {
|
|
return err
|
|
}
|
|
|
|
if nil == discoverService.DiscoveryConfig {
|
|
return fmt.Errorf("DiscoveryConfig of parameter is not valid")
|
|
}
|
|
ds.discoveryConfig = discoverService.DiscoveryConfig
|
|
}
|
|
|
|
_pCapScanner := pcap.NewPCapScanner(ds.zone)
|
|
if err := _pCapScanner.Start(); nil == err {
|
|
ds.pCapScanner = _pCapScanner
|
|
ds.privileged = true
|
|
log.Print("Privileged mode")
|
|
} else {
|
|
log.Print(err)
|
|
ds.privileged = false
|
|
log.Print("Unprivileged mode")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) PCapScanner() pcap.PCapScanner {
|
|
return ds.pCapScanner
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) Privileged() bool {
|
|
return ds.privileged
|
|
}
|
|
|
|
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 {
|
|
return ds.zone
|
|
}
|
|
func (ds *ofDiscoverySession) Host() *omd.Host {
|
|
return ds.host
|
|
}
|
|
func (ds *ofDiscoverySession) Port() *omd.Port {
|
|
return ds.port
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveryConfig() *omd.DiscoveryConfig {
|
|
return ds.discoveryConfig
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) TargetHosts() []net.IP {
|
|
return ds.targetHosts
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) IsTargetHost(host *omd.Host) bool {
|
|
if nil == ds.targetHostAddresses {
|
|
return false
|
|
}
|
|
|
|
if _, ok := ds.targetHostAddresses[host.Address]; ok {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) IsTargetPort(port *omd.Port) bool {
|
|
if nil == ds.targetPortNumbers || 0 == len(ds.targetPortNumbers) {
|
|
return false
|
|
}
|
|
|
|
portNumber, err := ouej.NumberToInt(port.PortNumber)
|
|
if nil != err {
|
|
return false
|
|
}
|
|
|
|
if !ds.IsTargetHost(port.Host) {
|
|
return false
|
|
}
|
|
|
|
if _, ok := ds.targetPortNumbers[portNumber]; ok {
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) IsTargetService(service *omd.Service) bool {
|
|
if nil == ds.discoverService {
|
|
return false
|
|
}
|
|
|
|
if !ds.IsTargetPort(service.Port) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) HostNeedScan(host *omd.Host, discovererType *omm.MetaDiscovererType) bool {
|
|
ds.hostScannedMtx.Lock()
|
|
defer ds.hostScannedMtx.Unlock()
|
|
|
|
sd, ok := ds.hostScanned[host.Address]
|
|
if !ok {
|
|
sd = make(map[string]bool)
|
|
sd[discovererType.Key] = true
|
|
ds.hostScanned[host.Address] = sd
|
|
return true
|
|
}
|
|
|
|
_, ok = sd[discovererType.Key]
|
|
if !ok {
|
|
sd[discovererType.Key] = true
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddHost(discoveredBy *omm.MetaDiscovererType, host *omd.Host, meta map[string]string) *omd.Host {
|
|
ds.discoveredMtx.Lock()
|
|
defer ds.discoveredMtx.Unlock()
|
|
|
|
h, modified := ds.findHost(host)
|
|
|
|
if "" == h.Mac && "" != host.Mac {
|
|
h.Mac = host.Mac
|
|
modified = true
|
|
}
|
|
|
|
if "" == h.OsType && "" != host.OsType {
|
|
h.OsType = host.OsType
|
|
modified = true
|
|
}
|
|
|
|
if omd.DefaultHostType == h.HostType && "" != host.HostType {
|
|
h.HostType = host.HostType
|
|
modified = true
|
|
}
|
|
|
|
if omd.DefaultHostVendor == h.HostVendor && "" != host.HostVendor {
|
|
h.HostVendor = host.HostVendor
|
|
modified = true
|
|
}
|
|
|
|
if omd.DefaultHostModel == h.HostModel && "" != host.HostModel {
|
|
h.HostModel = host.HostModel
|
|
modified = true
|
|
}
|
|
|
|
discoveredBys, discoveredByModified := ds.appendDiscoveredBy(discoveredBy, h.DiscoveredBy)
|
|
if discoveredByModified {
|
|
h.DiscoveredBy = discoveredBys
|
|
modified = true
|
|
}
|
|
|
|
metas, metaModified := ds.appendMeta(discoveredBy, h.Meta, meta)
|
|
if metaModified {
|
|
h.Meta = metas
|
|
modified = true
|
|
}
|
|
|
|
h, addtionalModified := ds.addtionalHost(discoveredBy, h)
|
|
if addtionalModified {
|
|
modified = true
|
|
}
|
|
|
|
if modified {
|
|
ds.delegate(h)
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddPort(discoveredBy *omm.MetaDiscovererType, port *omd.Port, meta map[string]string) *omd.Port {
|
|
ds.discoveredMtx.Lock()
|
|
defer ds.discoveredMtx.Unlock()
|
|
|
|
p, modified := ds.findPort(port)
|
|
|
|
discoveredBys, discoveredByModified := ds.appendDiscoveredBy(discoveredBy, p.DiscoveredBy)
|
|
if discoveredByModified {
|
|
p.DiscoveredBy = discoveredBys
|
|
modified = true
|
|
}
|
|
|
|
metas, metaModified := ds.appendMeta(discoveredBy, p.Meta, meta)
|
|
if metaModified {
|
|
p.Meta = metas
|
|
modified = metaModified
|
|
}
|
|
|
|
if modified {
|
|
ds.delegate(p)
|
|
}
|
|
|
|
return p
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddService(discoveredBy *omm.MetaDiscovererType, service *omd.Service, meta map[string]string) *omd.Service {
|
|
ds.discoveredMtx.Lock()
|
|
defer ds.discoveredMtx.Unlock()
|
|
|
|
s, modified := ds.findService(service)
|
|
|
|
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
|
|
}
|
|
|
|
discoveredBys, discoveredByModified := ds.appendDiscoveredBy(discoveredBy, s.DiscoveredBy)
|
|
if discoveredByModified {
|
|
s.DiscoveredBy = discoveredBys
|
|
modified = true
|
|
}
|
|
|
|
metas, metaModified := ds.appendMeta(discoveredBy, s.Meta, meta)
|
|
if metaModified {
|
|
s.Meta = metas
|
|
modified = metaModified
|
|
}
|
|
|
|
s, addtionalModified := ds.addtionalService(discoveredBy, s)
|
|
if addtionalModified {
|
|
modified = true
|
|
}
|
|
|
|
if modified {
|
|
ds.delegate(s)
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) AddServiceUnknown(discoveredBy *omm.MetaDiscovererType, 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
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveredHost(address string) *omd.Host {
|
|
ds.discoveredMtx.RLock()
|
|
defer ds.discoveredMtx.RUnlock()
|
|
|
|
h, ok := ds.hosts[address]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
return h
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveredAllHosts(includeMac bool) map[string]*omd.Host {
|
|
if includeMac {
|
|
return ds.includeMacHosts
|
|
}
|
|
return ds.hosts
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveredPort(host *omd.Host, portNumber int) map[string]*omd.Port {
|
|
ds.discoveredMtx.RLock()
|
|
defer ds.discoveredMtx.RUnlock()
|
|
|
|
h, _ := ds.findHost(host)
|
|
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
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveredAllPorts() map[*omd.Host]map[json.Number]map[string]*omd.Port {
|
|
return ds.ports
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveredService(port *omd.Port, name string) *omd.Service {
|
|
ds.discoveredMtx.RLock()
|
|
defer ds.discoveredMtx.RUnlock()
|
|
|
|
p, _ := ds.findPort(port)
|
|
if nil == p {
|
|
return nil
|
|
}
|
|
|
|
services, ok := ds.services[p]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
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]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
return services
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) DiscoveredAllServices() map[*omd.Port]map[string]*omd.Service {
|
|
return ds.services
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) StopChan() <-chan struct{} {
|
|
return ds.stopChan
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) delegate(data interface{}) {
|
|
if true == ds.stopped.Load().(bool) {
|
|
return
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
if nil != ds.discoveryDelegator {
|
|
ds.discoveryDelegator <- data
|
|
}
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) Shutdown() {
|
|
if ds.stopped.Load().(bool) {
|
|
return
|
|
}
|
|
|
|
ds.stopped.Store(true)
|
|
close(ds.stopChan)
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) findHost(host *omd.Host) (h *omd.Host, modified bool) {
|
|
modified = false
|
|
var ok bool
|
|
|
|
if "" == host.HostType {
|
|
host.HostType = omd.DefaultHostType
|
|
}
|
|
if "" == host.OsType {
|
|
host.OsType = omd.DefaultOsType
|
|
}
|
|
|
|
h, ok = ds.hosts[host.Address]
|
|
if !ok {
|
|
ds.hosts[host.Address] = host
|
|
if "" != host.Mac {
|
|
ds.includeMacHosts[host.Address] = host
|
|
}
|
|
h = host
|
|
modified = true
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) findPort(port *omd.Port) (p *omd.Port, modified bool) {
|
|
modified = false
|
|
var ok bool
|
|
|
|
h, _ := ds.findHost(port.Host)
|
|
if nil == h {
|
|
return
|
|
}
|
|
|
|
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]
|
|
}
|
|
|
|
p, ok = ports[port.MetaPortType.Key]
|
|
if !ok {
|
|
ports[port.MetaPortType.Key] = port
|
|
p = ports[port.MetaPortType.Key]
|
|
modified = true
|
|
}
|
|
|
|
if "" == p.DefaultService {
|
|
portNumber, _ := ouej.NumberToInt(port.PortNumber)
|
|
switch omm.ToMetaPortTypeEnum(port.MetaPortType) {
|
|
case omm.MetaPortTypeEnumTCP:
|
|
if dName, ok := layers.TCPPortNames[layers.TCPPort(portNumber)]; ok {
|
|
p.DefaultService = dName
|
|
modified = true
|
|
}
|
|
case omm.MetaPortTypeEnumUDP:
|
|
if dName, ok := layers.UDPPortNames[layers.UDPPort(portNumber)]; ok {
|
|
p.DefaultService = dName
|
|
modified = true
|
|
}
|
|
default:
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) findService(service *omd.Service) (s *omd.Service, modified bool) {
|
|
modified = false
|
|
var ok bool
|
|
|
|
p, _ := ds.findPort(service.Port)
|
|
if nil == p {
|
|
return
|
|
}
|
|
|
|
services, ok := ds.services[p]
|
|
if !ok {
|
|
ds.services[p] = make(map[string]*omd.Service)
|
|
services = ds.services[p]
|
|
} else {
|
|
if _, ok := services[omd.UnknownServiceKey]; ok {
|
|
delete(services, omd.UnknownServiceKey)
|
|
}
|
|
}
|
|
|
|
s, ok = services[service.Key]
|
|
if !ok {
|
|
services[service.Key] = service
|
|
s = services[service.Key]
|
|
modified = true
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) addtionalHost(discoveredBy *omm.MetaDiscovererType, host *omd.Host) (h *omd.Host, modified bool) {
|
|
h = host
|
|
modified = false
|
|
|
|
if nil == host.Meta {
|
|
return
|
|
}
|
|
|
|
meta, ok := host.Meta[discoveredBy.Key]
|
|
if !ok || nil == meta || 0 == len(meta) {
|
|
return
|
|
}
|
|
|
|
switch omm.ToMetaDiscovererTypeEnum(discoveredBy) {
|
|
case omm.MetaDiscovererTypeEnumMDNS:
|
|
_h, _modified := ds.addtionalHostMDNS(h, meta)
|
|
if _modified {
|
|
h = _h
|
|
modified = true
|
|
}
|
|
case omm.MetaDiscovererTypeEnumUPnP:
|
|
_h, _modified := ds.addtionalHostUPnP(h, meta)
|
|
if _modified {
|
|
h = _h
|
|
modified = true
|
|
}
|
|
}
|
|
|
|
if "" != h.HostVendor && "" != h.HostModel {
|
|
if "Synology" == h.HostVendor && strings.Contains(h.HostModel, "DS") {
|
|
h.HostType = omm.MetaHostTypeEnumNAS.String()
|
|
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 {
|
|
h.HostVendor = _vendor
|
|
modified = true
|
|
}
|
|
|
|
_model, ok := meta["model"]
|
|
if ok || "" != _model {
|
|
h.HostModel = _model
|
|
// if "Synology" == _vendor && strings.Contains(_model, "DS1817+") {
|
|
// if "Synology" == _vendor && strings.Contains(_model, "DS") {
|
|
// h.HostType = omm.MetaHostTypeEnumNAS.String()
|
|
// }
|
|
modified = true
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) addtionalHostUPnP(host *omd.Host, meta map[string]string) (h *omd.Host, modified bool) {
|
|
h = host
|
|
modified = false
|
|
|
|
_vendor, ok := meta["Manufacturer"]
|
|
if ok || "" != _vendor {
|
|
h.HostVendor = _vendor
|
|
modified = true
|
|
}
|
|
|
|
_model, ok := meta["ModelName"]
|
|
if ok || "" != _model {
|
|
h.HostModel = _model
|
|
// if "EFM Networks" == _vendor && strings.Contains(_model, "ipTIME A2004NS") {
|
|
// h.HostType = omm.MetaHostTypeEnumRouter.String()
|
|
// }
|
|
modified = true
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) addtionalService(discoveredBy *omm.MetaDiscovererType, service *omd.Service) (s *omd.Service, modified bool) {
|
|
s = service
|
|
modified = false
|
|
|
|
if nil == service.Meta {
|
|
return
|
|
}
|
|
|
|
meta, ok := service.Meta[discoveredBy.Key]
|
|
if !ok || nil == meta || 0 == len(meta) {
|
|
return
|
|
}
|
|
|
|
switch omm.ToMetaDiscovererTypeEnum(discoveredBy) {
|
|
case omm.MetaDiscovererTypeEnumMDNS:
|
|
_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.Name || "printer" == service.Key {
|
|
_h, _ := ds.findHost(service.Port.Host)
|
|
_h.HostType = omm.MetaHostTypeEnumPrinter.String()
|
|
_h.Name = service.Name
|
|
ds.delegate(_h)
|
|
}
|
|
case 9100:
|
|
if "pdl-datastream" == service.Name || "pdl-datastream" == service.Key {
|
|
_h, _ := ds.findHost(service.Port.Host)
|
|
_h.HostType = omm.MetaHostTypeEnumPrinter.String()
|
|
_h.Name = service.Name
|
|
ds.delegate(_h)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) appendDiscoveredBy(discoveredBy *omm.MetaDiscovererType, oriDiscoveredBy []*omm.MetaDiscovererType) (resultDiscoveredBy []*omm.MetaDiscovererType, modified bool) {
|
|
modified = false
|
|
|
|
if nil == discoveredBy {
|
|
resultDiscoveredBy = oriDiscoveredBy
|
|
return
|
|
}
|
|
|
|
if nil == oriDiscoveredBy {
|
|
resultDiscoveredBy = []*omm.MetaDiscovererType{
|
|
discoveredBy,
|
|
}
|
|
modified = true
|
|
return
|
|
}
|
|
|
|
for _, v := range oriDiscoveredBy {
|
|
if v.Key == discoveredBy.Key {
|
|
resultDiscoveredBy = oriDiscoveredBy
|
|
return
|
|
}
|
|
}
|
|
|
|
oriDiscoveredBy = append(oriDiscoveredBy, discoveredBy)
|
|
resultDiscoveredBy = oriDiscoveredBy
|
|
modified = true
|
|
|
|
return
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) appendMeta(discoveredBy *omm.MetaDiscovererType, oriMetas map[string]map[string]string, newMeta map[string]string) (resultMetas map[string]map[string]string, modified bool) {
|
|
modified = false
|
|
if nil == newMeta || 0 == len(newMeta) {
|
|
resultMetas = oriMetas
|
|
return
|
|
}
|
|
|
|
if nil == oriMetas {
|
|
resultMetas = map[string]map[string]string{
|
|
discoveredBy.Key: newMeta,
|
|
}
|
|
modified = true
|
|
return
|
|
}
|
|
|
|
oriMeta, ok := oriMetas[discoveredBy.Key]
|
|
if !ok {
|
|
oriMetas[discoveredBy.Key] = newMeta
|
|
resultMetas = oriMetas
|
|
return
|
|
}
|
|
|
|
LOOP:
|
|
for k, v := range newMeta {
|
|
_v, _ok := oriMeta[k]
|
|
if !_ok {
|
|
oriMeta[k] = v
|
|
modified = true
|
|
continue LOOP
|
|
}
|
|
|
|
_metas := strings.Split(_v, MetaSeperator)
|
|
for _, _meta := range _metas {
|
|
if _meta == v {
|
|
continue LOOP
|
|
}
|
|
}
|
|
|
|
oriMeta[k] = fmt.Sprintf("%s%s%s", _v, MetaSeperator, v)
|
|
modified = true
|
|
}
|
|
|
|
resultMetas = oriMetas
|
|
|
|
return
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setDiscoverHost(discoverHost *omd.DiscoverHost) error {
|
|
if nil == discoverHost {
|
|
return nil
|
|
}
|
|
|
|
if err := ds.setTargetHosts(ds.zone, discoverHost); nil != err {
|
|
return err
|
|
}
|
|
|
|
ds.discoverHost = discoverHost
|
|
|
|
return ds.setDiscoverPort(discoverHost.DiscoverPort)
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setDiscoverPort(discoverPort *omd.DiscoverPort) error {
|
|
if nil == discoverPort {
|
|
return nil
|
|
}
|
|
|
|
if err := ds.setTargetPortNumbers(discoverPort); nil != err {
|
|
return err
|
|
}
|
|
|
|
ds.discoverPort = discoverPort
|
|
return ds.setDiscoverService(discoverPort.DiscoverService)
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setDiscoverService(discoverService *omd.DiscoverService) error {
|
|
if nil == discoverService {
|
|
return nil
|
|
}
|
|
|
|
ds.discoverService = discoverService
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ds *ofDiscoverySession) setTargetHosts(zone *omd.Zone, discoverHost *omd.DiscoverHost) error {
|
|
cr, err := ounc.NewCIDRRanger(zone.Network)
|
|
if nil != err {
|
|
return err
|
|
}
|
|
|
|
var firstIP net.IP
|
|
if "" != discoverHost.FirstScanRange {
|
|
firstIP = net.ParseIP(discoverHost.FirstScanRange)
|
|
if nil == firstIP {
|
|
return 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 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 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 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 err
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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) {
|
|
ds.stopChan = nil
|
|
|
|
if nil != ds.pCapScanner {
|
|
ds.pCapScanner.Stop()
|
|
}
|
|
|
|
ds.pCapScanner = nil
|
|
ds.discoveryRequest = nil
|
|
ds.zone = nil
|
|
ds.host = nil
|
|
ds.port = nil
|
|
|
|
ds.discoveryConfig = nil
|
|
|
|
ds.discoverHost = nil
|
|
ds.discoverPort = nil
|
|
ds.discoverService = nil
|
|
|
|
ds.targetHosts = nil
|
|
ds.targetHostAddresses = nil
|
|
ds.targetPortNumbers = nil
|
|
|
|
ds.discoveryDelegator = nil
|
|
|
|
ds.includeMacHosts = nil
|
|
ds.hosts = nil
|
|
ds.ports = nil
|
|
ds.services = nil
|
|
ds.hostScanned = nil
|
|
|
|
discoverySessionPool.Put(ds)
|
|
}
|