icmp added
This commit is contained in:
parent
f95ca6bdf1
commit
0e953adb3d
19
discovery/protocol/icmp/icmp.go
Normal file
19
discovery/protocol/icmp/icmp.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package icmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
omm "git.loafle.net/overflow/model/meta"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Scan(discoverySession session.DiscoverySession) error {
|
||||||
|
metaIPTypeEnum := omm.ToMetaIPTypeEnum(discoverySession.Zone().MetaIPType)
|
||||||
|
|
||||||
|
switch metaIPTypeEnum {
|
||||||
|
case omm.MetaIPTypeEnumV4:
|
||||||
|
return scanV4(discoverySession)
|
||||||
|
case omm.MetaIPTypeEnumV6:
|
||||||
|
return scanV4(discoverySession)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
175
discovery/protocol/icmp/icmpv4.go
Normal file
175
discovery/protocol/icmp/icmpv4.go
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
package icmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
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"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/internal/pcap"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv4"
|
||||||
|
)
|
||||||
|
|
||||||
|
func scanV4(discoverySession session.DiscoverySession) error {
|
||||||
|
targetHosts := discoverySession.TargetHosts()
|
||||||
|
if nil == targetHosts || 0 == len(targetHosts) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
zone := discoverySession.Zone()
|
||||||
|
|
||||||
|
ps, err := pcap.RetainScanner(zone)
|
||||||
|
if nil != err {
|
||||||
|
return fmt.Errorf("Cannot retain pcap instance %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
pcap.ReleaseScanner(zone)
|
||||||
|
}()
|
||||||
|
|
||||||
|
icmpChan := ps.OpenICMP4()
|
||||||
|
defer func() {
|
||||||
|
ps.CloseICMP4(icmpChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
timerStopped := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
hosts := make(map[string]*omd.Host)
|
||||||
|
|
||||||
|
var delay atomic.Value
|
||||||
|
delay.Store(false)
|
||||||
|
ticker := time.NewTicker(time.Millisecond * 500)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case packet, ok := <-icmpChan:
|
||||||
|
if !ok {
|
||||||
|
// logging.Logger().Debugf("icmp channel is closed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delay.Store(true)
|
||||||
|
if h := handlePacketICMP4(zone, targetHosts, hosts, packet); nil != h {
|
||||||
|
if h != nil {
|
||||||
|
log.Println(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resultChan <- h
|
||||||
|
}
|
||||||
|
case <-ticker.C:
|
||||||
|
if false == delay.Load().(bool) {
|
||||||
|
ticker.Stop()
|
||||||
|
timerStopped <- struct{}{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delay.Store(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := sendICMP4(ps, zone, targetHosts); nil != err {
|
||||||
|
log.Printf("sendICMP %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timerStopped:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendICMP4(ps pcap.PCapScanner, zone *omd.Zone, targetHosts []net.IP) error {
|
||||||
|
conn, err := icmp.ListenPacket("ip4:icmp", "")
|
||||||
|
if nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
msg, err := makeMessageICMP4()
|
||||||
|
if nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var dst net.IPAddr
|
||||||
|
LOOP:
|
||||||
|
for _, targetHost := range targetHosts {
|
||||||
|
dst.IP = targetHost
|
||||||
|
if _, err := conn.WriteTo(msg, &dst); nil != err {
|
||||||
|
continue LOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
timer := time.NewTimer(time.Microsecond * 100)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePacketICMP4(zone *omd.Zone, targetHosts []net.IP, hosts map[string]*omd.Host, packet gopacket.Packet) *omd.Host {
|
||||||
|
_ethLayer := packet.Layer(layers.LayerTypeEthernet)
|
||||||
|
ethLayer := _ethLayer.(*layers.Ethernet)
|
||||||
|
|
||||||
|
_ip4Layer := packet.Layer(layers.LayerTypeIPv4)
|
||||||
|
ip4Layer := _ip4Layer.(*layers.IPv4)
|
||||||
|
|
||||||
|
_icmp4Layer := packet.Layer(layers.LayerTypeICMPv4)
|
||||||
|
icmp4Layer := _icmp4Layer.(*layers.ICMPv4)
|
||||||
|
|
||||||
|
if icmp4Layer.TypeCode != layers.ICMPv4TypeEchoReply {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := ip4Layer.SrcIP
|
||||||
|
if _, ok := hosts[ip.String()]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
isTarget := false
|
||||||
|
for _, h := range targetHosts {
|
||||||
|
if h.Equal(ip) {
|
||||||
|
isTarget = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !isTarget {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
h := &omd.Host{
|
||||||
|
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
|
||||||
|
Address: ip.String(),
|
||||||
|
Mac: net.HardwareAddr(ethLayer.SrcMAC).String(),
|
||||||
|
Zone: zone,
|
||||||
|
DiscoveredDate: omu.NowPtr(),
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts[ip.String()] = h
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeMessageICMP4() ([]byte, error) {
|
||||||
|
id := rand.Intn(0xffff)
|
||||||
|
seq := rand.Intn(0xffff)
|
||||||
|
|
||||||
|
return (&icmp.Message{
|
||||||
|
Type: ipv4.ICMPTypeEcho,
|
||||||
|
Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: id,
|
||||||
|
Seq: seq,
|
||||||
|
Data: []byte("PING by overFlow"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
}
|
125
discovery/protocol/icmp/icmpv4_test.go
Normal file
125
discovery/protocol/icmp/icmpv4_test.go
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
package icmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
omm "git.loafle.net/overflow/model/meta"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/session"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/discovery/types"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/internal/pcap"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_scanV4(t *testing.T) {
|
||||||
|
s := session.NewMockDiscoverySession(
|
||||||
|
"testRequester",
|
||||||
|
types.DiscoveryRequestTypeHost,
|
||||||
|
&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",
|
||||||
|
DiscoveryConfig: &omd.DiscoveryConfig{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
discoverySession session.DiscoverySession
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "1",
|
||||||
|
args: args{
|
||||||
|
discoverySession: s,
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := scanV4(tt.args.discoverySession); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("scanV4() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_sendICMP4(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
ps pcap.PCapScanner
|
||||||
|
zone *omd.Zone
|
||||||
|
targetHosts []net.IP
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if err := sendICMP4(tt.args.ps, tt.args.zone, tt.args.targetHosts); (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("sendICMP4() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_handlePacketICMP4(t *testing.T) {
|
||||||
|
type args struct {
|
||||||
|
zone *omd.Zone
|
||||||
|
targetHosts []net.IP
|
||||||
|
hosts map[string]*omd.Host
|
||||||
|
packet gopacket.Packet
|
||||||
|
}
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
args args
|
||||||
|
want *omd.Host
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
if got := handlePacketICMP4(tt.args.zone, tt.args.targetHosts, tt.args.hosts, tt.args.packet); !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("handlePacketICMP4() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_makeMessageICMP4(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
want []byte
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
// TODO: Add test cases.
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := makeMessageICMP4()
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("makeMessageICMP4() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
|
t.Errorf("makeMessageICMP4() = %v, want %v", got, tt.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
175
discovery/protocol/icmp/icmpv6.go
Normal file
175
discovery/protocol/icmp/icmpv6.go
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
package icmp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
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"
|
||||||
|
"git.loafle.net/overflow_scanner/probe/internal/pcap"
|
||||||
|
"github.com/google/gopacket"
|
||||||
|
"github.com/google/gopacket/layers"
|
||||||
|
"golang.org/x/net/icmp"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
|
)
|
||||||
|
|
||||||
|
func scanV6(discoverySession session.DiscoverySession) error {
|
||||||
|
targetHosts := discoverySession.TargetHosts()
|
||||||
|
if nil == targetHosts || 0 == len(targetHosts) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
zone := discoverySession.Zone()
|
||||||
|
|
||||||
|
ps, err := pcap.RetainScanner(zone)
|
||||||
|
if nil != err {
|
||||||
|
return fmt.Errorf("Cannot retain pcap instance %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
pcap.ReleaseScanner(zone)
|
||||||
|
}()
|
||||||
|
|
||||||
|
icmpChan := ps.OpenICMP6()
|
||||||
|
defer func() {
|
||||||
|
ps.CloseICMP6(icmpChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
timerStopped := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
hosts := make(map[string]*omd.Host)
|
||||||
|
|
||||||
|
var delay atomic.Value
|
||||||
|
delay.Store(false)
|
||||||
|
ticker := time.NewTicker(time.Millisecond * 500)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case packet, ok := <-icmpChan:
|
||||||
|
if !ok {
|
||||||
|
// logging.Logger().Debugf("icmp channel is closed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delay.Store(true)
|
||||||
|
if h := handlePacketICMP6(zone, targetHosts, hosts, packet); nil != h {
|
||||||
|
if h != nil {
|
||||||
|
log.Println(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
// resultChan <- h
|
||||||
|
}
|
||||||
|
case <-ticker.C:
|
||||||
|
if false == delay.Load().(bool) {
|
||||||
|
ticker.Stop()
|
||||||
|
timerStopped <- struct{}{}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delay.Store(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := sendICMP6(ps, zone, targetHosts); nil != err {
|
||||||
|
log.Printf("sendICMP %v", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timerStopped:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendICMP6(ps pcap.PCapScanner, zone *omd.Zone, targetHosts []net.IP) error {
|
||||||
|
conn, err := icmp.ListenPacket("ip6:ipv6-icmp", "")
|
||||||
|
if nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
msg, err := makeMessageICMP6()
|
||||||
|
if nil != err {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var dst net.IPAddr
|
||||||
|
LOOP:
|
||||||
|
for _, targetHost := range targetHosts {
|
||||||
|
dst.IP = targetHost
|
||||||
|
if _, err := conn.WriteTo(msg, &dst); nil != err {
|
||||||
|
continue LOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
timer := time.NewTimer(time.Microsecond * 100)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePacketICMP6(zone *omd.Zone, targetHosts []net.IP, hosts map[string]*omd.Host, packet gopacket.Packet) *omd.Host {
|
||||||
|
_ethLayer := packet.Layer(layers.LayerTypeEthernet)
|
||||||
|
ethLayer := _ethLayer.(*layers.Ethernet)
|
||||||
|
|
||||||
|
_ip6Layer := packet.Layer(layers.LayerTypeIPv6)
|
||||||
|
ip6Layer := _ip6Layer.(*layers.IPv6)
|
||||||
|
|
||||||
|
_icmp6Layer := packet.Layer(layers.LayerTypeICMPv6)
|
||||||
|
icmp6Layer := _icmp6Layer.(*layers.ICMPv6)
|
||||||
|
|
||||||
|
if icmp6Layer.TypeCode != layers.ICMPv6TypeEchoReply {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := ip6Layer.SrcIP
|
||||||
|
if _, ok := hosts[ip.String()]; ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
isTarget := false
|
||||||
|
for _, h := range targetHosts {
|
||||||
|
if h.Equal(ip) {
|
||||||
|
isTarget = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !isTarget {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
h := &omd.Host{
|
||||||
|
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV6),
|
||||||
|
Address: ip.String(),
|
||||||
|
Mac: net.HardwareAddr(ethLayer.SrcMAC).String(),
|
||||||
|
Zone: zone,
|
||||||
|
DiscoveredDate: omu.NowPtr(),
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts[ip.String()] = h
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeMessageICMP6() ([]byte, error) {
|
||||||
|
id := rand.Intn(0xffff)
|
||||||
|
seq := rand.Intn(0xffff)
|
||||||
|
|
||||||
|
return (&icmp.Message{
|
||||||
|
Type: ipv6.ICMPTypeEchoRequest,
|
||||||
|
Code: 0,
|
||||||
|
Body: &icmp.Echo{
|
||||||
|
ID: id,
|
||||||
|
Seq: seq,
|
||||||
|
Data: []byte("PING by overFlow"),
|
||||||
|
},
|
||||||
|
}).Marshal(nil)
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ SERVICE_LOOP:
|
||||||
|
|
||||||
ENTRY_LOOP:
|
ENTRY_LOOP:
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
// log.Print("serviceEntry ", entry)
|
log.Print("serviceEntry ", entry)
|
||||||
|
|
||||||
name := entry.Instance // HP\ LaserJet\ P1505n
|
name := entry.Instance // HP\ LaserJet\ P1505n
|
||||||
service := entry.Service // _pdl-datastream._tcp
|
service := entry.Service // _pdl-datastream._tcp
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
omd "git.loafle.net/overflow/model/discovery"
|
omd "git.loafle.net/overflow/model/discovery"
|
||||||
|
@ -26,13 +27,17 @@ type DiscoverySession interface {
|
||||||
DiscoverPort() *omd.DiscoverPort
|
DiscoverPort() *omd.DiscoverPort
|
||||||
DiscoverService() *omd.DiscoverService
|
DiscoverService() *omd.DiscoverService
|
||||||
|
|
||||||
|
TargetHosts() []net.IP
|
||||||
|
|
||||||
|
SetDiscoveryDelegator(chan<- interface{})
|
||||||
|
|
||||||
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
|
DiscoveredHost(address string) *omd.Host
|
||||||
|
DiscoveredPort(host *omd.Host, portNumber int) map[string]*omd.Port
|
||||||
SetDiscoveryDelegator(chan<- interface{})
|
DiscoveredService(port *omd.Port, name string) map[string]*omd.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
type ofDiscoverySession struct {
|
type ofDiscoverySession struct {
|
||||||
|
@ -243,6 +248,53 @@ func (ds *ofDiscoverySession) AddService(service *omd.Service) *omd.Service {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *ofDiscoverySession) DiscoveredHost(address string) *omd.Host {
|
||||||
|
h, ok := ds.hosts[address]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *ofDiscoverySession) DiscoveredPort(host *omd.Host, portNumber int) map[string]*omd.Port {
|
||||||
|
h, _ := ds.findHost(host, false)
|
||||||
|
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) DiscoveredService(port *omd.Port, name string) map[string]*omd.Service {
|
||||||
|
p, _ := ds.findPort(port, false)
|
||||||
|
if nil == p {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
portServices, ok := ds.services[p]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
services, ok := portServices[name]
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return services
|
||||||
|
}
|
||||||
|
|
||||||
func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) (h *omd.Host, modified bool) {
|
func (ds *ofDiscoverySession) findHost(host *omd.Host, add bool) (h *omd.Host, modified bool) {
|
||||||
modified = false
|
modified = false
|
||||||
var ok bool
|
var ok bool
|
||||||
|
|
|
@ -10,6 +10,8 @@ type PacketType int
|
||||||
const (
|
const (
|
||||||
PacketTypeUnknown PacketType = iota
|
PacketTypeUnknown PacketType = iota
|
||||||
PacketTypeARP
|
PacketTypeARP
|
||||||
|
PacketTypeICMPv4
|
||||||
|
PacketTypeICMPv6
|
||||||
PacketTypeTCP
|
PacketTypeTCP
|
||||||
PacketTypeUDP
|
PacketTypeUDP
|
||||||
)
|
)
|
||||||
|
@ -23,6 +25,16 @@ func getPacketType(packet gopacket.Packet) PacketType {
|
||||||
return PacketTypeARP
|
return PacketTypeARP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layer = packet.Layer(layers.LayerTypeICMPv4)
|
||||||
|
if layer != nil {
|
||||||
|
return PacketTypeICMPv4
|
||||||
|
}
|
||||||
|
|
||||||
|
layer = packet.Layer(layers.LayerTypeICMPv6)
|
||||||
|
if layer != nil {
|
||||||
|
return PacketTypeICMPv6
|
||||||
|
}
|
||||||
|
|
||||||
layer = packet.Layer(layers.LayerTypeTCP)
|
layer = packet.Layer(layers.LayerTypeTCP)
|
||||||
if layer != nil {
|
if layer != nil {
|
||||||
if _, ok := layer.(*layers.TCP); ok {
|
if _, ok := layer.(*layers.TCP); ok {
|
||||||
|
@ -43,6 +55,10 @@ func handlePacket(ps *pCapScan, packet gopacket.Packet) {
|
||||||
switch getPacketType(packet) {
|
switch getPacketType(packet) {
|
||||||
case PacketTypeARP:
|
case PacketTypeARP:
|
||||||
handlePacketARP(ps, packet)
|
handlePacketARP(ps, packet)
|
||||||
|
case PacketTypeICMPv4:
|
||||||
|
handlePacketICMP4(ps, packet)
|
||||||
|
case PacketTypeICMPv6:
|
||||||
|
handlePacketICMP6(ps, packet)
|
||||||
case PacketTypeTCP:
|
case PacketTypeTCP:
|
||||||
handlePacketTCP(ps, packet)
|
handlePacketTCP(ps, packet)
|
||||||
case PacketTypeUDP:
|
case PacketTypeUDP:
|
||||||
|
@ -63,6 +79,30 @@ func handlePacketARP(ps *pCapScan, packet gopacket.Packet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handlePacketICMP4(ps *pCapScan, packet gopacket.Packet) {
|
||||||
|
ps.icmp4ListenerChanMtx.RLock()
|
||||||
|
defer ps.icmp4ListenerChanMtx.RUnlock()
|
||||||
|
|
||||||
|
// icmp4Layer := packet.Layer(layers.LayerTypeICMPv4)
|
||||||
|
// icmp4 := icmp4Layer.(*layers.ICMPv4)
|
||||||
|
|
||||||
|
for _, ch := range ps.icmp4ListenerChans {
|
||||||
|
ch <- packet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlePacketICMP6(ps *pCapScan, packet gopacket.Packet) {
|
||||||
|
ps.icmp6ListenerChanMtx.RLock()
|
||||||
|
defer ps.icmp6ListenerChanMtx.RUnlock()
|
||||||
|
|
||||||
|
// icmp6Layer := packet.Layer(layers.LayerTypeICMPv6)
|
||||||
|
// icmp6 := icmp6Layer.(*layers.ICMPv6)
|
||||||
|
|
||||||
|
for _, ch := range ps.icmp6ListenerChans {
|
||||||
|
ch <- packet
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func handlePacketTCP(ps *pCapScan, packet gopacket.Packet) {
|
func handlePacketTCP(ps *pCapScan, packet gopacket.Packet) {
|
||||||
ipLayer := packet.Layer(layers.LayerTypeIPv4)
|
ipLayer := packet.Layer(layers.LayerTypeIPv4)
|
||||||
if nil == ipLayer {
|
if nil == ipLayer {
|
||||||
|
|
|
@ -23,6 +23,12 @@ type PCapScanner interface {
|
||||||
OpenARP() chan *layers.ARP
|
OpenARP() chan *layers.ARP
|
||||||
CloseARP(ch chan *layers.ARP)
|
CloseARP(ch chan *layers.ARP)
|
||||||
|
|
||||||
|
OpenICMP4() chan gopacket.Packet
|
||||||
|
CloseICMP4(ch chan gopacket.Packet)
|
||||||
|
|
||||||
|
OpenICMP6() chan gopacket.Packet
|
||||||
|
CloseICMP6(ch chan gopacket.Packet)
|
||||||
|
|
||||||
OpenTCP(ip string) chan *layers.TCP
|
OpenTCP(ip string) chan *layers.TCP
|
||||||
CloseTCP(ip string, ch chan *layers.TCP)
|
CloseTCP(ip string, ch chan *layers.TCP)
|
||||||
|
|
||||||
|
@ -45,6 +51,12 @@ type pCapScan struct {
|
||||||
arpListenerChanMtx sync.RWMutex
|
arpListenerChanMtx sync.RWMutex
|
||||||
arpListenerChans []chan *layers.ARP
|
arpListenerChans []chan *layers.ARP
|
||||||
|
|
||||||
|
icmp4ListenerChanMtx sync.RWMutex
|
||||||
|
icmp4ListenerChans []chan gopacket.Packet
|
||||||
|
|
||||||
|
icmp6ListenerChanMtx sync.RWMutex
|
||||||
|
icmp6ListenerChans []chan gopacket.Packet
|
||||||
|
|
||||||
tcpListenerChanMtx sync.RWMutex
|
tcpListenerChanMtx sync.RWMutex
|
||||||
tcpListenerChans map[string][]chan *layers.TCP
|
tcpListenerChans map[string][]chan *layers.TCP
|
||||||
|
|
||||||
|
@ -70,13 +82,15 @@ func (ps *pCapScan) start() error {
|
||||||
// set filter
|
// set filter
|
||||||
// todo add tcp, udp filter
|
// todo add tcp, udp filter
|
||||||
//if err = h.SetBPFFilter("arp and src net " + ps.zone.Network + " or (((tcp[tcpflags] & (tcp-syn|tcp-ack) != 0) or (tcp[tcpflags] & (tcp-rst) != 0)) and port 60000) or udp "); nil != err {
|
//if err = h.SetBPFFilter("arp and src net " + ps.zone.Network + " or (((tcp[tcpflags] & (tcp-syn|tcp-ack) != 0) or (tcp[tcpflags] & (tcp-rst) != 0)) and port 60000) or udp "); nil != err {
|
||||||
if err = h.SetBPFFilter("arp or tcp or udp"); nil != err {
|
if err = h.SetBPFFilter("arp or icmp or icmp6 or tcp or udp"); nil != err {
|
||||||
h.Close()
|
h.Close()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ps.pCapHandle = h
|
ps.pCapHandle = h
|
||||||
|
|
||||||
ps.arpListenerChans = make([]chan *layers.ARP, 0)
|
ps.arpListenerChans = make([]chan *layers.ARP, 0)
|
||||||
|
ps.icmp4ListenerChans = make([]chan gopacket.Packet, 0)
|
||||||
|
ps.icmp6ListenerChans = make([]chan gopacket.Packet, 0)
|
||||||
ps.tcpListenerChans = make(map[string][]chan *layers.TCP, 0)
|
ps.tcpListenerChans = make(map[string][]chan *layers.TCP, 0)
|
||||||
ps.udpListenerChans = make(map[string][]chan gopacket.Packet, 0)
|
ps.udpListenerChans = make(map[string][]chan gopacket.Packet, 0)
|
||||||
|
|
||||||
|
@ -119,6 +133,50 @@ func (ps *pCapScan) CloseARP(ch chan *layers.ARP) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ps *pCapScan) OpenICMP4() chan gopacket.Packet {
|
||||||
|
ps.icmp4ListenerChanMtx.Lock()
|
||||||
|
defer ps.icmp4ListenerChanMtx.Unlock()
|
||||||
|
|
||||||
|
c := make(chan gopacket.Packet, 0)
|
||||||
|
ps.icmp4ListenerChans = append(ps.icmp4ListenerChans, c)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
func (ps *pCapScan) CloseICMP4(ch chan gopacket.Packet) {
|
||||||
|
ps.icmp4ListenerChanMtx.Lock()
|
||||||
|
defer ps.icmp4ListenerChanMtx.Unlock()
|
||||||
|
|
||||||
|
i := sort.Search(len(ps.icmp4ListenerChans), func(i int) bool {
|
||||||
|
return ch == ps.icmp4ListenerChans[i]
|
||||||
|
})
|
||||||
|
|
||||||
|
if -1 != i {
|
||||||
|
close(ch)
|
||||||
|
ps.icmp4ListenerChans = append(ps.icmp4ListenerChans[:i], ps.icmp4ListenerChans[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ps *pCapScan) OpenICMP6() chan gopacket.Packet {
|
||||||
|
ps.icmp6ListenerChanMtx.Lock()
|
||||||
|
defer ps.icmp6ListenerChanMtx.Unlock()
|
||||||
|
|
||||||
|
c := make(chan gopacket.Packet, 0)
|
||||||
|
ps.icmp6ListenerChans = append(ps.icmp6ListenerChans, c)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
func (ps *pCapScan) CloseICMP6(ch chan gopacket.Packet) {
|
||||||
|
ps.icmp6ListenerChanMtx.Lock()
|
||||||
|
defer ps.icmp6ListenerChanMtx.Unlock()
|
||||||
|
|
||||||
|
i := sort.Search(len(ps.icmp6ListenerChans), func(i int) bool {
|
||||||
|
return ch == ps.icmp6ListenerChans[i]
|
||||||
|
})
|
||||||
|
|
||||||
|
if -1 != i {
|
||||||
|
close(ch)
|
||||||
|
ps.icmp6ListenerChans = append(ps.icmp6ListenerChans[:i], ps.icmp6ListenerChans[i+1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (ps *pCapScan) OpenTCP(ip string) chan *layers.TCP {
|
func (ps *pCapScan) OpenTCP(ip string) chan *layers.TCP {
|
||||||
ps.tcpListenerChanMtx.Lock()
|
ps.tcpListenerChanMtx.Lock()
|
||||||
defer ps.tcpListenerChanMtx.Unlock()
|
defer ps.tcpListenerChanMtx.Unlock()
|
||||||
|
@ -222,6 +280,20 @@ func (ps *pCapScan) destroy() {
|
||||||
}
|
}
|
||||||
ps.udpListenerChanMtx.Unlock()
|
ps.udpListenerChanMtx.Unlock()
|
||||||
|
|
||||||
|
ps.icmp4ListenerChanMtx.Lock()
|
||||||
|
for _, v := range ps.icmp4ListenerChans {
|
||||||
|
close(v)
|
||||||
|
}
|
||||||
|
ps.icmp4ListenerChans = ps.icmp4ListenerChans[:0]
|
||||||
|
ps.icmp4ListenerChanMtx.Unlock()
|
||||||
|
|
||||||
|
ps.icmp6ListenerChanMtx.Lock()
|
||||||
|
for _, v := range ps.icmp6ListenerChans {
|
||||||
|
close(v)
|
||||||
|
}
|
||||||
|
ps.icmp6ListenerChans = ps.icmp6ListenerChans[:0]
|
||||||
|
ps.icmp6ListenerChanMtx.Unlock()
|
||||||
|
|
||||||
ps.arpListenerChanMtx.Lock()
|
ps.arpListenerChanMtx.Lock()
|
||||||
for _, v := range ps.arpListenerChans {
|
for _, v := range ps.arpListenerChans {
|
||||||
close(v)
|
close(v)
|
||||||
|
@ -235,7 +307,7 @@ func (ps *pCapScan) destroy() {
|
||||||
func handleReceive(ps *pCapScan) {
|
func handleReceive(ps *pCapScan) {
|
||||||
defer ps.stopWg.Done()
|
defer ps.stopWg.Done()
|
||||||
|
|
||||||
pSrc := gopacket.NewPacketSource(ps.pCapHandle, layers.LayerTypeEthernet)
|
pSrc := gopacket.NewPacketSource(ps.pCapHandle, ps.pCapHandle.LinkType())
|
||||||
inPacket := pSrc.Packets()
|
inPacket := pSrc.Packets()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user