diff --git a/README.md b/README.md index 7b37008..0f18a66 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # go-lanscan -![Coverage](https://img.shields.io/badge/Coverage-91.8%25-brightgreen) +![Coverage](https://img.shields.io/badge/Coverage-92.6%25-brightgreen) A network cli and golang package that allows you to perform arp and syn scanning on a local area network. @@ -62,6 +62,13 @@ sudo go-lanscan --no-progress --json # run only arp scanning (skip syn scanning) sudo go-lanscan --arp-only + +# set timing - this is how fast packets are sent to hosts +# default is 100µs between packets +# the faster you send packets (shorter the timing), the less accurate the results will be +sudo go-lanscan --timing 1ms # set to 1 millisecond +sudo go-lanscan --timing 500µs # set to 500 microseconds +sudo go-lanscan --timing 500us # alternate symbol for microseconds ``` ## Package Usage @@ -84,6 +91,31 @@ First you must install the following dependencies You can provide the following options to all scanners +- Provide specific timing duration + +This option is used to set a specific time to wait between sending packets +to hosts. The default is 100µs. The shorter the timing, the faster packets +will be sent, and the less accurate your results will be + +```go + timing := time.Microsecond * 200 + + fullScanner := scanner.NewFullScanner( + netInfo, + targets, + ports, + listenPort, + scanner.WithTiming(timing), + ) + + // or + fullScanner.SetTiming(timing) + + // or + option := scanner.WithTiming(timing) + option(fullScanner) +``` + - Provide channel for notifications when packet requests are sent to target ```go @@ -100,11 +132,11 @@ You can provide the following options to all scanners ) // or - option := scanner.WithRequestNotifications(requests) - option(requests) + synScanner.SetRequestNotifications(requests) // or - synScanner.SetRequestNotifications(requests) + option := scanner.WithRequestNotifications(requests) + option(synScanner) ``` - Provide your own idle timeout. If no packets are received from our targets diff --git a/internal/cli/root.go b/internal/cli/root.go index 273fe50..3aadf55 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -3,18 +3,98 @@ package cli import ( + "fmt" + "os" "strings" "time" + "github.com/jedib0t/go-pretty/table" "github.com/spf13/cobra" "github.com/robgonnella/go-lanscan/internal/core" + "github.com/robgonnella/go-lanscan/internal/logger" "github.com/robgonnella/go-lanscan/internal/util" "github.com/robgonnella/go-lanscan/pkg/network" "github.com/robgonnella/go-lanscan/pkg/oui" "github.com/robgonnella/go-lanscan/pkg/scanner" ) +func printConfiguration( + coreScanner scanner.Scanner, + targets []string, + cidr string, + ports []string, + ifaceName string, + listenPort uint16, + timing string, + vendorInfo, + printJson, + arpOnly, + progress bool, + outFile string, +) { + var configTable = table.NewWriter() + + configTable.SetOutputMirror(os.Stdout) + + configTable.AppendRow(table.Row{ + "scannerType", + fmt.Sprintf("%T", coreScanner), + }) + + configTable.AppendRow(table.Row{ + "targets", + targets, + }) + + configTable.AppendRow(table.Row{ + "cidr", + cidr, + }) + + configTable.AppendRow(table.Row{ + "ports", + ports, + }) + + configTable.AppendRow(table.Row{ + "interface", + ifaceName, + }) + + configTable.AppendRow(table.Row{ + "listenPort", + listenPort, + }) + + configTable.AppendRow(table.Row{ + "timing", + timing, + }) + + configTable.AppendRow(table.Row{ + "vendorInfo", + vendorInfo, + }) + + configTable.AppendRow(table.Row{ + "json", + printJson, + }) + + configTable.AppendRow(table.Row{ + "arpOnly", + arpOnly, + }) + + configTable.AppendRow(table.Row{ + "progress", + progress, + }) + + configTable.Render() +} + func Root( runner core.Runner, userNet network.Network, @@ -23,6 +103,7 @@ func Root( var printJson bool var noProgress bool var ports string + var timing string var idleTimeoutSeconds int var listenPort uint16 var ifaceName string @@ -36,6 +117,8 @@ func Root( Short: "Scan your LAN!", Long: `CLI to scan your Local Area Network`, RunE: func(cmd *cobra.Command, args []string) error { + log := logger.New() + portList := strings.Split(ports, ",") if ifaceName != userNet.Interface().Name { @@ -74,6 +157,15 @@ func Root( coreScanner.IncludeVendorInfo(vendorRepo) } + timingDuration, err := time.ParseDuration(timing) + + if err != nil { + log.Error().Err(err).Msg("invalid timing value") + return err + } + + coreScanner.SetTiming(timingDuration) + portLen := util.PortTotal(portList) targetLen := util.TotalTargets(targets) @@ -92,10 +184,28 @@ func Root( outFile, ) + if !noProgress { + printConfiguration( + coreScanner, + targets, + userNet.Cidr(), + portList, + userNet.Interface().Name, + listenPort, + timing, + vendorInfo, + printJson, + arpOnly, + !noProgress, + outFile, + ) + } + return runner.Run() }, } + cmd.Flags().StringVar(&timing, "timing", "100µs", "set time between packet sends - the faster you send the less accurate the result will be") cmd.Flags().BoolVar(&printJson, "json", false, "output json instead of table text") cmd.Flags().BoolVar(&arpOnly, "arp-only", false, "only perform arp scanning (skip syn scanning)") cmd.Flags().BoolVar(&noProgress, "no-progress", false, "disable all output except for final results") diff --git a/internal/cli/root_test.go b/internal/cli/root_test.go index e5a047c..d03c8cf 100644 --- a/internal/cli/root_test.go +++ b/internal/cli/root_test.go @@ -18,7 +18,7 @@ func TestRootCommand(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - t.Run("initializes and runs full scanner", func(st *testing.T) { + t.Run("returns error if invalid timing duration is supplied", func(st *testing.T) { mockNetwork := mock_network.NewMockNetwork(ctrl) mockRunner := mock_core.NewMockRunner(ctrl) @@ -40,6 +40,41 @@ func TestRootCommand(t *testing.T) { mockNetwork.EXPECT().IPNet().AnyTimes().Return(mockIPNet) + cmd, err := cli.Root(mockRunner, mockNetwork, mockVendor) + + assert.NoError(st, err) + + cmd.SetArgs([]string{"--timing", "nope"}) + + err = cmd.Execute() + + assert.Error(st, err) + }) + + t.Run("initializes and runs full scanner and includes vendor info", func(st *testing.T) { + mockNetwork := mock_network.NewMockNetwork(ctrl) + + mockRunner := mock_core.NewMockRunner(ctrl) + + mockVendor := mock_oui.NewMockVendorRepo(ctrl) + + mockMAC, _ := net.ParseMAC("00:00:00:00:00:00") + + mockCidr := "172.17.1.1/32" + + _, mockIPNet, _ := net.ParseCIDR(mockCidr) + + mockNetwork.EXPECT().Interface().AnyTimes().Return(&net.Interface{ + Name: "test-interface", + HardwareAddr: mockMAC, + }) + + mockNetwork.EXPECT().Cidr().AnyTimes().Return(mockCidr) + + mockNetwork.EXPECT().IPNet().AnyTimes().Return(mockIPNet) + + mockVendor.EXPECT().UpdateVendors().Times(1) + mockRunner.EXPECT().Initialize( gomock.Any(), 1, @@ -56,7 +91,7 @@ func TestRootCommand(t *testing.T) { assert.NoError(st, err) - cmd.SetArgs([]string{}) + cmd.SetArgs([]string{"--vendor"}) err = cmd.Execute() diff --git a/mock/scanner/scanner.go b/mock/scanner/scanner.go index dee3c27..88061f7 100644 --- a/mock/scanner/scanner.go +++ b/mock/scanner/scanner.go @@ -117,6 +117,18 @@ func (mr *MockScannerMockRecorder) SetRequestNotifications(arg0 any) *gomock.Cal return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetRequestNotifications", reflect.TypeOf((*MockScanner)(nil).SetRequestNotifications), arg0) } +// SetTiming mocks base method. +func (m *MockScanner) SetTiming(arg0 time.Duration) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetTiming", arg0) +} + +// SetTiming indicates an expected call of SetTiming. +func (mr *MockScannerMockRecorder) SetTiming(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTiming", reflect.TypeOf((*MockScanner)(nil).SetTiming), arg0) +} + // Stop mocks base method. func (m *MockScanner) Stop() { m.ctrl.T.Helper() diff --git a/pkg/scanner/arpscan.go b/pkg/scanner/arpscan.go index 43fa2d8..e03f94b 100644 --- a/pkg/scanner/arpscan.go +++ b/pkg/scanner/arpscan.go @@ -30,6 +30,7 @@ type ArpScanner struct { requestNotifier chan *Request scanning bool lastPacketSentAt time.Time + timing time.Duration idleTimeout time.Duration vendorRepo oui.VendorRepo scanningMux *sync.RWMutex @@ -51,7 +52,8 @@ func NewArpScanner( cap: &defaultPacketCapture{}, networkInfo: networkInfo, resultChan: make(chan *ScanResult), - idleTimeout: time.Second * 5, + timing: defaultTiming, + idleTimeout: defaultIdleTimeout, scanning: false, lastPacketSentAt: time.Time{}, scanningMux: &sync.RWMutex{}, @@ -108,7 +110,7 @@ func (s *ArpScanner) Scan() error { go s.readPackets() - limiter := time.NewTicker(defaultAccuracy) + limiter := time.NewTicker(s.timing) defer limiter.Stop() if len(s.targets) == 0 { @@ -142,6 +144,10 @@ func (s *ArpScanner) Stop() { } } +func (s *ArpScanner) SetTiming(d time.Duration) { + s.timing = d +} + func (s *ArpScanner) SetRequestNotifications(c chan *Request) { s.requestNotifier = c } diff --git a/pkg/scanner/arpscan_test.go b/pkg/scanner/arpscan_test.go index 2e7db05..b192b16 100644 --- a/pkg/scanner/arpscan_test.go +++ b/pkg/scanner/arpscan_test.go @@ -115,6 +115,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false arpScanner := scanner.NewArpScanner( []string{}, @@ -141,10 +142,6 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) @@ -154,6 +151,13 @@ func TestArpScanner(t *testing.T) { firstCall = false return nil, gopacket.CaptureInfo{}, errors.New("mock ReadPacketData error") } + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockNonIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, @@ -171,6 +175,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false arpScanner := scanner.NewArpScanner( []string{}, @@ -197,14 +202,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockNonIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, @@ -222,6 +230,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false arpScanner := scanner.NewArpScanner( []string{"172.17.1.1"}, @@ -247,14 +256,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockNonIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, @@ -272,6 +284,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false arpScanner := scanner.NewArpScanner( []string{"172.17.1.1"}, @@ -297,14 +310,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpRequestReadResult() }) @@ -319,6 +335,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false arpScanner := scanner.NewArpScanner( []string{"172.17.1.1"}, @@ -344,14 +361,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockNonIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // scanning host hw address @@ -369,6 +389,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false arpScanner := scanner.NewArpScanner( []string{"172.17.1.1"}, @@ -394,14 +415,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, @@ -420,6 +444,7 @@ func TestArpScanner(t *testing.T) { handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) vendorRepo := mock_oui.NewMockVendorRepo(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false vendorRepo.EXPECT().UpdateVendors().Times(1) @@ -448,14 +473,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, @@ -481,6 +509,7 @@ func TestArpScanner(t *testing.T) { handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) vendorRepo := mock_oui.NewMockVendorRepo(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false vendorRepo.EXPECT().UpdateVendors().Times(1) @@ -509,14 +538,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, @@ -558,6 +590,7 @@ func TestArpScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) mockNetInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false requestNotifier := make(chan *scanner.Request) @@ -591,14 +624,17 @@ func TestArpScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - arpScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + arpScanner.Stop() + wg.Done() + }() + } return test_helper.NewArpReplyReadResult( mockIncludedArpSrcIP, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, diff --git a/pkg/scanner/fullscan.go b/pkg/scanner/fullscan.go index caaaa1a..47b3195 100644 --- a/pkg/scanner/fullscan.go +++ b/pkg/scanner/fullscan.go @@ -148,6 +148,11 @@ func (s *FullScanner) Stop() { s.debug.Info().Msg("all scanners stopped") } +func (s *FullScanner) SetTiming(d time.Duration) { + s.arpScanner.SetTiming(d) + s.synScanner.SetTiming(d) +} + func (s *FullScanner) SetRequestNotifications(c chan *Request) { s.arpScanner.SetRequestNotifications(c) s.synScanner.SetRequestNotifications(c) diff --git a/pkg/scanner/options.go b/pkg/scanner/options.go index 94c2710..65012c0 100644 --- a/pkg/scanner/options.go +++ b/pkg/scanner/options.go @@ -11,7 +11,10 @@ import ( // How long to wait before sending next packet // the faster you send packets the more packets // will be missed when reading -const defaultAccuracy = time.Microsecond * 100 +const defaultTiming = time.Microsecond * 100 + +// If no packets are received for this period of time, exit with timeout +const defaultIdleTimeout = time.Second * 5 type ScannerOption = func(s Scanner) @@ -38,3 +41,9 @@ func WithPacketCapture(cap PacketCapture) ScannerOption { s.SetPacketCapture(cap) } } + +func WithTiming(duration time.Duration) ScannerOption { + return func(s Scanner) { + s.SetTiming(duration) + } +} diff --git a/pkg/scanner/options_test.go b/pkg/scanner/options_test.go index 0fbf11f..3003e32 100644 --- a/pkg/scanner/options_test.go +++ b/pkg/scanner/options_test.go @@ -30,6 +30,7 @@ func TestOptions(t *testing.T) { scanner.NewArpScanner( []string{}, netInfo, + scanner.WithTiming(time.Millisecond), scanner.WithIdleTimeout(time.Second*5), scanner.WithPacketCapture(testPacketCapture), scanner.WithRequestNotifications(requestNotifier), @@ -41,6 +42,7 @@ func TestOptions(t *testing.T) { []string{}, []string{}, 54321, + scanner.WithTiming(time.Millisecond), scanner.WithIdleTimeout(time.Second*5), scanner.WithPacketCapture(testPacketCapture), scanner.WithRequestNotifications(requestNotifier), @@ -52,6 +54,7 @@ func TestOptions(t *testing.T) { netInfo, []string{}, 54321, + scanner.WithTiming(time.Millisecond), scanner.WithIdleTimeout(time.Second*5), scanner.WithPacketCapture(testPacketCapture), scanner.WithRequestNotifications(requestNotifier), diff --git a/pkg/scanner/synscan.go b/pkg/scanner/synscan.go index 757a308..0537dd5 100644 --- a/pkg/scanner/synscan.go +++ b/pkg/scanner/synscan.go @@ -37,6 +37,7 @@ type SynScanner struct { requestNotifier chan *Request scanning bool lastPacketSentAt time.Time + timing time.Duration idleTimeout time.Duration scanningMux *sync.RWMutex packetSentAtMux *sync.RWMutex @@ -62,7 +63,8 @@ func NewSynScanner( ports: ports, listenPort: listenPort, resultChan: make(chan *ScanResult), - idleTimeout: time.Second * 5, + timing: defaultTiming, + idleTimeout: defaultIdleTimeout, scanning: false, lastPacketSentAt: time.Time{}, scanningMux: &sync.RWMutex{}, @@ -135,7 +137,7 @@ func (s *SynScanner) Scan() error { go s.readPackets() - limiter := time.NewTicker(defaultAccuracy) + limiter := time.NewTicker(s.timing) defer limiter.Stop() for _, target := range s.targets { @@ -170,6 +172,10 @@ func (s *SynScanner) Stop() { } } +func (s *SynScanner) SetTiming(d time.Duration) { + s.timing = d +} + func (s *SynScanner) SetRequestNotifications(c chan *Request) { s.requestNotifier = c } @@ -210,12 +216,14 @@ func (s *SynScanner) readPackets() { if err != nil { s.debug.Error().Err(err).Msg("syn: read packet error") + continue } err = parser.DecodeLayers(packetData, &decoded) if err != nil { s.debug.Error().Err(err).Msg("syn: decode packet error") + continue } synPacket := &SynPacket{} diff --git a/pkg/scanner/synscan_test.go b/pkg/scanner/synscan_test.go index d225474..b83845c 100644 --- a/pkg/scanner/synscan_test.go +++ b/pkg/scanner/synscan_test.go @@ -123,6 +123,7 @@ func TestSynScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) netInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false wg := sync.WaitGroup{} wg.Add(1) @@ -159,10 +160,6 @@ func TestSynScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - synScanner.Stop() - wg.Done() - }() return nil }) @@ -173,6 +170,13 @@ func TestSynScanner(t *testing.T) { firstCall = false return nil, gopacket.CaptureInfo{}, errors.New("mock ReadPacketData error") } + if !packetSent { + packetSent = true + defer func() { + synScanner.Stop() + wg.Done() + }() + } return test_helper.NewSynWithAckResponsePacketBytes( net.ParseIP("172.17.1.1"), 22, @@ -339,6 +343,7 @@ func TestSynScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) netInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false wg := sync.WaitGroup{} wg.Add(1) @@ -375,14 +380,17 @@ func TestSynScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - synScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + synScanner.Stop() + wg.Done() + }() + } return test_helper.NewSynWithAckResponsePacketBytes( net.ParseIP("172.17.1.1"), 22, @@ -401,6 +409,7 @@ func TestSynScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) netInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false wg := sync.WaitGroup{} wg.Add(1) @@ -437,14 +446,17 @@ func TestSynScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - synScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + synScanner.Stop() + wg.Done() + }() + } return test_helper.NewSynWithAckResponsePacketBytes( net.ParseIP("192.168.22.1"), 3000, @@ -463,6 +475,7 @@ func TestSynScanner(t *testing.T) { cap := mock_scanner.NewMockPacketCapture(ctrl) handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) netInfo := mock_network.NewMockNetwork(ctrl) + packetSent := false wg := sync.WaitGroup{} wg.Add(1) @@ -499,14 +512,17 @@ func TestSynScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - synScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + synScanner.Stop() + wg.Done() + }() + } return test_helper.NewSynWithAckResponsePacketBytes( net.ParseIP("172.17.1.1"), 3000, @@ -526,6 +542,7 @@ func TestSynScanner(t *testing.T) { handle := mock_scanner.NewMockPacketCaptureHandle(ctrl) netInfo := mock_network.NewMockNetwork(ctrl) requestNotifier := make(chan *scanner.Request) + packetSent := false notified := false wg := sync.WaitGroup{} @@ -570,14 +587,17 @@ func TestSynScanner(t *testing.T) { handle.EXPECT().Close().AnyTimes() handle.EXPECT().WritePacketData(gomock.Any()).DoAndReturn(func(data []byte) (err error) { - defer func() { - synScanner.Stop() - wg.Done() - }() return nil }) handle.EXPECT().ReadPacketData().AnyTimes().DoAndReturn(func() (data []byte, ci gopacket.CaptureInfo, err error) { + if !packetSent { + packetSent = true + defer func() { + synScanner.Stop() + wg.Done() + }() + } return test_helper.NewSynWithAckResponsePacketBytes( net.ParseIP("172.17.1.1"), 3000, diff --git a/pkg/scanner/types.go b/pkg/scanner/types.go index a344ed0..b91f186 100644 --- a/pkg/scanner/types.go +++ b/pkg/scanner/types.go @@ -30,6 +30,7 @@ type Scanner interface { Scan() error Stop() Results() chan *ScanResult + SetTiming(d time.Duration) SetRequestNotifications(c chan *Request) SetIdleTimeout(d time.Duration) IncludeVendorInfo(repo oui.VendorRepo)