Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplifies scanner timeouts #27

Merged
merged 1 commit into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# go-lanscan
![Coverage](https://img.shields.io/badge/Coverage-91.3%25-brightgreen)
![Coverage](https://img.shields.io/badge/Coverage-91.6%25-brightgreen)

A network cli and golang package that allows you to perform arp and syn
scanning on a local area network.
Expand Down
62 changes: 11 additions & 51 deletions pkg/scanner/arpscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@ type ArpScanner struct {
resultChan chan *ScanResult
requestNotifier chan *Request
scanning bool
lastPacketSentAt time.Time
timing time.Duration
idleTimeout time.Duration
vendorRepo oui.VendorRepo
hostNamesEnables bool
scanningMux *sync.RWMutex
packetSentAtMux *sync.RWMutex
debug logger.DebugLogger
}

Expand All @@ -45,18 +43,16 @@ func NewArpScanner(
options ...Option,
) *ArpScanner {
scanner := &ArpScanner{
cancel: make(chan struct{}),
targets: targets,
cap: &defaultPacketCapture{},
networkInfo: networkInfo,
resultChan: make(chan *ScanResult),
timing: defaultTiming,
idleTimeout: defaultIdleTimeout,
scanning: false,
lastPacketSentAt: time.Time{},
scanningMux: &sync.RWMutex{},
packetSentAtMux: &sync.RWMutex{},
debug: logger.NewDebugLogger(),
cancel: make(chan struct{}),
targets: targets,
cap: &defaultPacketCapture{},
networkInfo: networkInfo,
resultChan: make(chan *ScanResult),
timing: defaultTiming,
idleTimeout: defaultIdleTimeout,
scanning: false,
scanningMux: &sync.RWMutex{},
debug: logger.NewDebugLogger(),
}

for _, o := range options {
Expand Down Expand Up @@ -110,9 +106,6 @@ func (s *ArpScanner) Scan() error {
s.scanningMux.Unlock()
s.handle = handle

timeout := make(chan struct{})

go s.startPacketReceiveTimeout(timeout)
go s.readPackets()

limiter := time.NewTicker(s.timing)
Expand All @@ -134,11 +127,7 @@ func (s *ArpScanner) Scan() error {
})
}

s.packetSentAtMux.Lock()
s.lastPacketSentAt = time.Now()
s.packetSentAtMux.Unlock()

<-timeout
time.Sleep(s.idleTimeout)

go s.Stop()

Expand Down Expand Up @@ -197,31 +186,6 @@ func (s *ArpScanner) SetPacketCapture(cap PacketCapture) {
s.cap = cap
}

func (s *ArpScanner) startPacketReceiveTimeout(timeout chan<- struct{}) {
for {
select {
case <-s.cancel:
go func() {
timeout <- struct{}{}
}()
return
default:
s.packetSentAtMux.RLock()
packetSentAt := s.lastPacketSentAt
s.packetSentAtMux.RUnlock()

if !packetSentAt.IsZero() && time.Since(packetSentAt) >= s.idleTimeout {
go func() {
timeout <- struct{}{}
}()
return
}

time.Sleep(time.Millisecond * 100)
}
}
}

func (s *ArpScanner) readPackets() {
for {
select {
Expand Down Expand Up @@ -367,8 +331,4 @@ func (s *ArpScanner) reset() {
s.scanningMux.Lock()
s.scanning = false
s.scanningMux.Unlock()

s.packetSentAtMux.Lock()
s.lastPacketSentAt = time.Time{}
s.packetSentAtMux.Unlock()
}
98 changes: 29 additions & 69 deletions pkg/scanner/synscan.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,21 @@ type SynPacket struct {

// SynScanner implements the Scanner interface for SYN scanning
type SynScanner struct {
cancel chan struct{}
networkInfo network.Network
targets []*ArpScanResult
ports []string
listenPort uint16
cap PacketCapture
handle PacketCaptureHandle
resultChan chan *ScanResult
requestNotifier chan *Request
scanning bool
lastPacketSentAt time.Time
timing time.Duration
idleTimeout time.Duration
scanningMux *sync.RWMutex
packetSentAtMux *sync.RWMutex
serviceQueryMux *sync.Mutex
debug logger.DebugLogger
cancel chan struct{}
networkInfo network.Network
targets []*ArpScanResult
ports []string
listenPort uint16
cap PacketCapture
handle PacketCaptureHandle
resultChan chan *ScanResult
requestNotifier chan *Request
scanning bool
timing time.Duration
idleTimeout time.Duration
scanningMux *sync.RWMutex
serviceQueryMux *sync.Mutex
debug logger.DebugLogger
}

// NewSynScanner returns a new instance of SYNScanner
Expand All @@ -54,21 +52,19 @@ func NewSynScanner(
options ...Option,
) *SynScanner {
scanner := &SynScanner{
cancel: make(chan struct{}),
targets: targets,
networkInfo: networkInfo,
cap: &defaultPacketCapture{},
ports: ports,
listenPort: listenPort,
resultChan: make(chan *ScanResult),
timing: defaultTiming,
idleTimeout: defaultIdleTimeout,
scanning: false,
lastPacketSentAt: time.Time{},
scanningMux: &sync.RWMutex{},
packetSentAtMux: &sync.RWMutex{},
serviceQueryMux: &sync.Mutex{},
debug: logger.NewDebugLogger(),
cancel: make(chan struct{}),
targets: targets,
networkInfo: networkInfo,
cap: &defaultPacketCapture{},
ports: ports,
listenPort: listenPort,
resultChan: make(chan *ScanResult),
timing: defaultTiming,
idleTimeout: defaultIdleTimeout,
scanning: false,
scanningMux: &sync.RWMutex{},
serviceQueryMux: &sync.Mutex{},
debug: logger.NewDebugLogger(),
}

for _, o := range options {
Expand Down Expand Up @@ -138,9 +134,6 @@ func (s *SynScanner) Scan() error {

s.handle = handle

timeout := make(chan struct{})

go s.startPacketReceiveTimeout(timeout)
go s.readPackets()

limiter := time.NewTicker(s.timing)
Expand All @@ -163,11 +156,7 @@ func (s *SynScanner) Scan() error {
}
}

s.packetSentAtMux.Lock()
s.lastPacketSentAt = time.Now()
s.packetSentAtMux.Unlock()

<-timeout
time.Sleep(s.idleTimeout)

go s.Stop()

Expand Down Expand Up @@ -228,31 +217,6 @@ func (s *SynScanner) SetTargets(targets []*ArpScanResult) {
s.targets = targets
}

func (s *SynScanner) startPacketReceiveTimeout(timeout chan<- struct{}) {
for {
select {
case <-s.cancel:
go func() {
timeout <- struct{}{}
}()
return
default:
s.packetSentAtMux.RLock()
packetSentAt := s.lastPacketSentAt
s.packetSentAtMux.RUnlock()

if !packetSentAt.IsZero() && time.Since(packetSentAt) >= s.idleTimeout {
go func() {
timeout <- struct{}{}
}()
return
}

time.Sleep(time.Millisecond * 100)
}
}
}

func (s *SynScanner) readPackets() {
for {
select {
Expand Down Expand Up @@ -418,8 +382,4 @@ func (s *SynScanner) reset() {
s.scanningMux.Lock()
s.scanning = false
s.scanningMux.Unlock()

s.packetSentAtMux.Lock()
s.lastPacketSentAt = time.Time{}
s.packetSentAtMux.Unlock()
}