ing
This commit is contained in:
		
							parent
							
								
									c28149db4b
								
							
						
					
					
						commit
						558e13da2e
					
				@ -6,10 +6,11 @@ import (
 | 
			
		||||
 | 
			
		||||
	omd "git.loafle.net/overflow/model/discovery"
 | 
			
		||||
	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/types"
 | 
			
		||||
	"git.loafle.net/overflow_scanner/probe/internal/protocol/mdns"
 | 
			
		||||
	"git.loafle.net/overflow_scanner/probe/internal/protocol/upnp"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Discoverer interface {
 | 
			
		||||
@ -47,21 +48,25 @@ type ofDiscoverer struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
	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) {
 | 
			
		||||
	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 {
 | 
			
		||||
	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() {
 | 
			
		||||
	if d.stopChan == nil {
 | 
			
		||||
		return
 | 
			
		||||
@ -89,18 +94,18 @@ func (d *ofDiscoverer) start() {
 | 
			
		||||
func (d *ofDiscoverer) enqueue(req *ofDiscoveryRequest) {
 | 
			
		||||
	select {
 | 
			
		||||
	case d.requestQueue <- req:
 | 
			
		||||
		req.SendMessage(types.DiscoveryMessageTypeQueueing, omu.Now(), nil)
 | 
			
		||||
		d.SendMessage(req, types.DiscoveryMessageTypeQueueing, omu.Now(), nil)
 | 
			
		||||
		go func() {
 | 
			
		||||
			select {
 | 
			
		||||
			case <-req.dequeue:
 | 
			
		||||
			case <-time.After(10 * time.Second):
 | 
			
		||||
				req.timeout = true
 | 
			
		||||
				req.SendMessage(types.DiscoveryMessageTypeTimeout, omu.Now(), nil)
 | 
			
		||||
				d.SendMessage(req, types.DiscoveryMessageTypeTimeout, omu.Now(), nil)
 | 
			
		||||
				req.release()
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
	default:
 | 
			
		||||
		req.SendMessage(types.DiscoveryMessageTypeFailedQueueing, omu.Now(), nil)
 | 
			
		||||
		d.SendMessage(req, types.DiscoveryMessageTypeFailedQueueing, omu.Now(), nil)
 | 
			
		||||
		req.release()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -122,9 +127,9 @@ LOOP:
 | 
			
		||||
			}
 | 
			
		||||
			req.(*ofDiscoveryRequest).dequeue <- true
 | 
			
		||||
 | 
			
		||||
			req.SendMessage(types.DiscoveryMessageTypeStart, omu.Now(), nil)
 | 
			
		||||
			d.SendMessage(req, types.DiscoveryMessageTypeStart, omu.Now(), nil)
 | 
			
		||||
			d.discover(req)
 | 
			
		||||
			req.SendMessage(types.DiscoveryMessageTypeStop, omu.Now(), nil)
 | 
			
		||||
			d.SendMessage(req, types.DiscoveryMessageTypeStop, omu.Now(), nil)
 | 
			
		||||
 | 
			
		||||
			req.(*ofDiscoveryRequest).release()
 | 
			
		||||
		case <-d.stopChan:
 | 
			
		||||
@ -144,17 +149,43 @@ func (d *ofDiscoverer) discover(req types.DiscoveryRequest) {
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if err := s.InitWithRequest(req); nil != err {
 | 
			
		||||
		req.SendMessage(types.DiscoveryMessageTypeError, nil, err)
 | 
			
		||||
		d.SendMessage(req, types.DiscoveryMessageTypeError, nil, err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	d.preDiscovery(s)
 | 
			
		||||
	d.layerDiscovery(s)
 | 
			
		||||
	d.complexDiscover(s)
 | 
			
		||||
	d.hierarchyDiscover(s)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *ofDiscoverer) preDiscovery(s session.DiscoverySession) {
 | 
			
		||||
func (d *ofDiscoverer) complexDiscover(s session.DiscoverySession) {
 | 
			
		||||
	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)
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer wg.Done()
 | 
			
		||||
@ -167,11 +198,15 @@ func (d *ofDiscoverer) preDiscovery(s session.DiscoverySession) {
 | 
			
		||||
		mdns.Scan(s)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	wg.Add(1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer wg.Done()
 | 
			
		||||
		snmp.Scan(s)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (d *ofDiscoverer) layerDiscovery(s session.DiscoverySession) {
 | 
			
		||||
	// SNMP
 | 
			
		||||
	// mDNS
 | 
			
		||||
	// UPnP
 | 
			
		||||
func (d *ofDiscoverer) hierarchyDiscover(s session.DiscoverySession) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -11,9 +11,8 @@ type ofDiscoveryRequest struct {
 | 
			
		||||
	requestType types.DiscoveryRequestType
 | 
			
		||||
	params      []interface{}
 | 
			
		||||
 | 
			
		||||
	messageChan chan<- types.DiscoveryMessage
 | 
			
		||||
	dequeue     chan bool
 | 
			
		||||
	timeout     bool
 | 
			
		||||
	dequeue chan bool
 | 
			
		||||
	timeout bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (dr *ofDiscoveryRequest) RequesterID() string {
 | 
			
		||||
@ -28,17 +27,13 @@ func (dr *ofDiscoveryRequest) Params() []interface{} {
 | 
			
		||||
	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() {
 | 
			
		||||
	releaseDiscoveryRequest(dr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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()
 | 
			
		||||
	var dr *ofDiscoveryRequest
 | 
			
		||||
	if v == nil {
 | 
			
		||||
@ -50,7 +45,6 @@ func retainDiscoveryRequest(messageChan chan<- types.DiscoveryMessage, requester
 | 
			
		||||
	dr.requesterID = requesterID
 | 
			
		||||
	dr.requestType = requestType
 | 
			
		||||
	dr.params = params
 | 
			
		||||
	dr.messageChan = messageChan
 | 
			
		||||
	dr.dequeue = make(chan bool, 1)
 | 
			
		||||
	dr.timeout = false
 | 
			
		||||
 | 
			
		||||
@ -61,7 +55,6 @@ func releaseDiscoveryRequest(dr *ofDiscoveryRequest) {
 | 
			
		||||
	dr.requesterID = ""
 | 
			
		||||
	dr.requestType = types.DiscoveryRequestTypeNone
 | 
			
		||||
	dr.params = nil
 | 
			
		||||
	dr.messageChan = nil
 | 
			
		||||
	close(dr.dequeue)
 | 
			
		||||
	dr.dequeue = nil
 | 
			
		||||
	dr.timeout = false
 | 
			
		||||
 | 
			
		||||
@ -1,69 +1,141 @@
 | 
			
		||||
package snmp
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	omcc "git.loafle.net/overflow/model/config/credential"
 | 
			
		||||
	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"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var defaultPort = 161
 | 
			
		||||
var defaultOIDs = []string{
 | 
			
		||||
	"1.3.6.1.2.1.1.5.0", //sysName
 | 
			
		||||
const (
 | 
			
		||||
	defaultPort      = 161
 | 
			
		||||
	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 {
 | 
			
		||||
	Host  *omd.Host
 | 
			
		||||
	Value map[string]string
 | 
			
		||||
	Error error
 | 
			
		||||
}
 | 
			
		||||
func scanV2(target net.IP, discoverySession session.DiscoverySession, credential *omcc.SNMPCredential) bool {
 | 
			
		||||
 | 
			
		||||
func ScanSNMP(host *omd.Host, community string, ch chan *SNMPResponse) {
 | 
			
		||||
	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)
 | 
			
		||||
	address := fmt.Sprintf("%s:%d", target.String(), credential.Port)
 | 
			
		||||
	snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
 | 
			
		||||
		Version:   snmpgo.V2c,
 | 
			
		||||
		Address:   address,
 | 
			
		||||
		Retries:   1,
 | 
			
		||||
		Community: community,
 | 
			
		||||
		Community: credential.Community,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ch <- &SNMPResponse{host, nil, err}
 | 
			
		||||
		return
 | 
			
		||||
		// ch <- &SNMPResponse{host, nil, err}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	defer snmp.Close()
 | 
			
		||||
 | 
			
		||||
	oids, err := snmpgo.NewOids(_oids)
 | 
			
		||||
	oids, err := snmpgo.NewOids(defaultOIDs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ch <- &SNMPResponse{host, nil, err}
 | 
			
		||||
		return
 | 
			
		||||
		// ch <- &SNMPResponse{host, nil, err}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pdu, err := snmp.GetRequest(oids)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ch <- &SNMPResponse{host, nil, err}
 | 
			
		||||
		return
 | 
			
		||||
		// ch <- &SNMPResponse{host, nil, err}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if pdu.ErrorStatus() != snmpgo.NoError {
 | 
			
		||||
		ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())}
 | 
			
		||||
		return
 | 
			
		||||
		// ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", pdu.ErrorStatus().String())}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if pdu == nil {
 | 
			
		||||
		ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")}
 | 
			
		||||
		return
 | 
			
		||||
		// ch <- &SNMPResponse{host, nil, fmt.Errorf("%s", "Empty PDU")}
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resMap := make(map[string]string)
 | 
			
		||||
	meta := make(map[string]string)
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,21 +3,36 @@ package snmp
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	omd "git.loafle.net/overflow/model/discovery"
 | 
			
		||||
	omm "git.loafle.net/overflow/model/meta"
 | 
			
		||||
	"git.loafle.net/overflow_scanner/probe/discovery"
 | 
			
		||||
	"git.loafle.net/overflow_scanner/probe/discovery/session"
 | 
			
		||||
	"git.loafle.net/overflow_scanner/probe/discovery/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestSNMPScan(t *testing.T) {
 | 
			
		||||
	host := &omd.Host{
 | 
			
		||||
		MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
 | 
			
		||||
		Address:    "192.168.1.229",
 | 
			
		||||
	}
 | 
			
		||||
	s := session.MockDiscoverySession()
 | 
			
		||||
	s.InitWithRequest(
 | 
			
		||||
		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)
 | 
			
		||||
	defer close(ch)
 | 
			
		||||
	ScanSNMP(host, "test1252serc", ch)
 | 
			
		||||
	Scan(s)
 | 
			
		||||
 | 
			
		||||
	msg := <-ch
 | 
			
		||||
	t.Log(msg)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,26 +3,36 @@ package session
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	omd "git.loafle.net/overflow/model/discovery"
 | 
			
		||||
	ounc "git.loafle.net/overflow/util-go/net/cidr"
 | 
			
		||||
	"git.loafle.net/overflow_scanner/probe/discovery/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DiscoverySession interface {
 | 
			
		||||
	InitWithRequest(request types.DiscoveryRequest) error
 | 
			
		||||
 | 
			
		||||
	DiscoveryRequest() types.DiscoveryRequest
 | 
			
		||||
 | 
			
		||||
	Zone() *omd.Zone
 | 
			
		||||
	Host() *omd.Host
 | 
			
		||||
	Port() *omd.Port
 | 
			
		||||
 | 
			
		||||
	DiscoveryConfig() *omd.DiscoveryConfig
 | 
			
		||||
 | 
			
		||||
	DiscoverHost() *omd.DiscoverHost
 | 
			
		||||
	DiscoverPort() *omd.DiscoverPort
 | 
			
		||||
	DiscoverService() *omd.DiscoverService
 | 
			
		||||
 | 
			
		||||
	InitWithRequest(request types.DiscoveryRequest) error
 | 
			
		||||
 | 
			
		||||
	AddHost(host *omd.Host) *omd.Host
 | 
			
		||||
	AddPort(port *omd.Port) *omd.Port
 | 
			
		||||
	AddService(service *omd.Service) *omd.Service
 | 
			
		||||
 | 
			
		||||
	TargetHosts() []net.IP
 | 
			
		||||
 | 
			
		||||
	SetDiscoveryDelegator(chan<- interface{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ofDiscoverySession struct {
 | 
			
		||||
@ -32,10 +42,16 @@ type ofDiscoverySession struct {
 | 
			
		||||
	host *omd.Host
 | 
			
		||||
	port *omd.Port
 | 
			
		||||
 | 
			
		||||
	discoveryConfig *omd.DiscoveryConfig
 | 
			
		||||
 | 
			
		||||
	discoverHost    *omd.DiscoverHost
 | 
			
		||||
	discoverPort    *omd.DiscoverPort
 | 
			
		||||
	discoverService *omd.DiscoverService
 | 
			
		||||
 | 
			
		||||
	targetHosts []net.IP
 | 
			
		||||
 | 
			
		||||
	discoveryDelegator chan<- interface{}
 | 
			
		||||
 | 
			
		||||
	hosts    map[string]*omd.Host
 | 
			
		||||
	ports    map[*omd.Host]map[json.Number]map[string]*omd.Port
 | 
			
		||||
	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")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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.setDiscoverHost(discoverHost)
 | 
			
		||||
	case types.DiscoveryRequestTypePort:
 | 
			
		||||
@ -93,6 +120,11 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
 | 
			
		||||
			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.setDiscoverPort(discoverPort)
 | 
			
		||||
	case types.DiscoveryRequestTypeService:
 | 
			
		||||
@ -110,6 +142,11 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
 | 
			
		||||
			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.setDiscoverService(discoverService)
 | 
			
		||||
	}
 | 
			
		||||
@ -117,6 +154,14 @@ func (ds *ofDiscoverySession) InitWithRequest(request types.DiscoveryRequest) er
 | 
			
		||||
	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 {
 | 
			
		||||
	return ds.zone
 | 
			
		||||
}
 | 
			
		||||
@ -127,6 +172,10 @@ 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
 | 
			
		||||
}
 | 
			
		||||
@ -137,59 +186,93 @@ func (ds *ofDiscoverySession) DiscoverService() *omd.DiscoverService {
 | 
			
		||||
	return ds.discoverService
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *ofDiscoverySession) TargetHosts() []net.IP {
 | 
			
		||||
	return ds.targetHosts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
		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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) *omd.Host {
 | 
			
		||||
	h, ok := ds.hosts[host.Address]
 | 
			
		||||
func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) (h *omd.Host, modified bool) {
 | 
			
		||||
	modified = false
 | 
			
		||||
	var ok bool
 | 
			
		||||
 | 
			
		||||
	h, ok = ds.hosts[host.Address]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ds.hosts[host.Address] = host
 | 
			
		||||
		h = host
 | 
			
		||||
		modified = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return h
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *ofDiscoverySession) findPort(port *omd.Port, add bool) *omd.Port {
 | 
			
		||||
	h := ds.findHost(port.Host, false)
 | 
			
		||||
func (ds *ofDiscoverySession) findPort(port *omd.Port, add bool) (p *omd.Port, modified bool) {
 | 
			
		||||
	modified = false
 | 
			
		||||
	var ok bool
 | 
			
		||||
 | 
			
		||||
	h, _ := ds.findHost(port.Host, false)
 | 
			
		||||
	if nil == h {
 | 
			
		||||
		return nil
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hostPorts, ok := ds.ports[h]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		hostPorts[port.PortNumber] = make(map[string]*omd.Port)
 | 
			
		||||
		ports = hostPorts[port.PortNumber]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p, ok := ports[port.MetaPortType.Key]
 | 
			
		||||
	p, ok = ports[port.MetaPortType.Key]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ports[port.MetaPortType.Key] = port
 | 
			
		||||
		p = ports[port.MetaPortType.Key]
 | 
			
		||||
		modified = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *ofDiscoverySession) findService(service *omd.Service, add bool) *omd.Service {
 | 
			
		||||
	p := ds.findPort(service.Port, false)
 | 
			
		||||
func (ds *ofDiscoverySession) findService(service *omd.Service, add bool) (s *omd.Service, modified bool) {
 | 
			
		||||
	modified = false
 | 
			
		||||
	var ok bool
 | 
			
		||||
 | 
			
		||||
	p, _ := ds.findPort(service.Port, false)
 | 
			
		||||
	if nil == p {
 | 
			
		||||
		return nil
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	portServices, ok := ds.services[p]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		portServices[service.Key] = make(map[string]*omd.Service)
 | 
			
		||||
		services = portServices[service.Key]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s, ok := services[service.MetaCryptoType.Key]
 | 
			
		||||
	s, ok = services[service.MetaCryptoType.Key]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		if !add {
 | 
			
		||||
			return nil
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		services[service.MetaCryptoType.Key] = service
 | 
			
		||||
		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 {
 | 
			
		||||
		return oriMeta
 | 
			
		||||
		resultMap = oriMeta
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if nil == oriMeta {
 | 
			
		||||
		return newMeta
 | 
			
		||||
		resultMap = newMeta
 | 
			
		||||
		modified = true
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
LOOP:
 | 
			
		||||
	for k, v := range oriMeta {
 | 
			
		||||
	for k, v := range newMeta {
 | 
			
		||||
		_v, _ok := oriMeta[k]
 | 
			
		||||
		if !_ok {
 | 
			
		||||
			oriMeta[k] = v
 | 
			
		||||
			modified = true
 | 
			
		||||
			continue LOOP
 | 
			
		||||
		}
 | 
			
		||||
		if v == _v {
 | 
			
		||||
			continue LOOP
 | 
			
		||||
		}
 | 
			
		||||
		oriMeta[k] = fmt.Sprintf("%s|||%s", _v, v)
 | 
			
		||||
		modified = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return oriMeta
 | 
			
		||||
	resultMap = oriMeta
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ds *ofDiscoverySession) setZone(zone *omd.Zone) {
 | 
			
		||||
@ -331,6 +427,53 @@ func (ds *ofDiscoverySession) setDiscoverService(discoverService *omd.DiscoverSe
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
func RetainDiscoverySession() *ofDiscoverySession {
 | 
			
		||||
 | 
			
		||||
@ -36,6 +36,4 @@ type DiscoveryRequest interface {
 | 
			
		||||
	RequesterID() string
 | 
			
		||||
	RequestType() DiscoveryRequestType
 | 
			
		||||
	Params() []interface{}
 | 
			
		||||
 | 
			
		||||
	SendMessage(messageType DiscoveryMessageType, data interface{}, err error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user