main.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // WiFi Scanner - captures WiFi probe requests and publishes events via ZMQ
  2. package main
  3. import (
  4. "context"
  5. "encoding/json"
  6. "flag"
  7. "log"
  8. "os"
  9. "os/signal"
  10. "syscall"
  11. "time"
  12. "mybeacon/internal/protocol"
  13. "mybeacon/internal/wifi"
  14. "github.com/go-zeromq/zmq4"
  15. )
  16. const (
  17. defaultZMQAddr = "tcp://127.0.0.1:5556"
  18. defaultIface = "wlan0"
  19. )
  20. var defaultChannels = []int{1, 6, 11}
  21. func main() {
  22. var (
  23. zmqAddr = flag.String("zmq", defaultZMQAddr, "ZMQ PUB address")
  24. iface = flag.String("iface", defaultIface, "WiFi interface")
  25. dwellMs = flag.Int("dwell", 400, "Channel dwell time in ms")
  26. debug = flag.Bool("debug", false, "Enable debug logging")
  27. noMonitor = flag.Bool("no-monitor", false, "Skip monitor mode setup")
  28. )
  29. flag.Parse()
  30. log.SetFlags(log.Ltime | log.Lmicroseconds)
  31. log.Printf("WiFi Scanner starting (iface=%s, zmq=%s)", *iface, *zmqAddr)
  32. ctx, cancel := context.WithCancel(context.Background())
  33. defer cancel()
  34. // Create ZMQ publisher socket
  35. publisher := zmq4.NewPub(ctx)
  36. defer publisher.Close()
  37. if err := publisher.Listen(*zmqAddr); err != nil {
  38. log.Fatalf("ZMQ listen: %v", err)
  39. }
  40. log.Printf("ZMQ PUB listening on %s", *zmqAddr)
  41. time.Sleep(100 * time.Millisecond)
  42. // Enable monitor mode
  43. if !*noMonitor {
  44. log.Printf("Enabling monitor mode on %s...", *iface)
  45. if err := wifi.SetMonitorMode(*iface); err != nil {
  46. log.Fatalf("Monitor mode: %v", err)
  47. }
  48. log.Printf("Monitor mode enabled on %s", *iface)
  49. }
  50. // Create capture socket
  51. capture, err := wifi.NewCaptureSocket(*iface)
  52. if err != nil {
  53. log.Fatalf("Capture socket: %v", err)
  54. }
  55. defer capture.Close()
  56. // Start channel hopper
  57. hopper := wifi.NewChannelHopper(*iface, defaultChannels, time.Duration(*dwellMs)*time.Millisecond)
  58. hopper.Start()
  59. defer hopper.Stop()
  60. log.Printf("Channel hopping: %v (dwell=%dms)", defaultChannels, *dwellMs)
  61. // Handle shutdown
  62. sigChan := make(chan os.Signal, 1)
  63. signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
  64. go func() {
  65. <-sigChan
  66. log.Println("Shutting down...")
  67. hopper.Stop()
  68. capture.Close()
  69. if !*noMonitor {
  70. wifi.SetManagedMode(*iface)
  71. }
  72. cancel()
  73. os.Exit(0)
  74. }()
  75. // Main capture loop
  76. buf := make([]byte, 65536)
  77. var eventCount uint64
  78. for {
  79. n, err := capture.Read(buf)
  80. if err != nil {
  81. log.Printf("Read error: %v", err)
  82. continue
  83. }
  84. probe, ok := wifi.ParseProbeRequest(buf[:n])
  85. if !ok {
  86. continue
  87. }
  88. ev := protocol.WiFiProbeEvent{
  89. Type: protocol.EventWiFiProbe,
  90. MAC: probe.SourceMAC,
  91. RSSI: probe.RSSI,
  92. TsMs: probe.Timestamp.UnixMilli(),
  93. SSID: probe.SSID,
  94. }
  95. jsonData, err := json.Marshal(ev)
  96. if err != nil {
  97. continue
  98. }
  99. topic := "wifi.probe"
  100. msg := zmq4.NewMsgString(topic + " " + string(jsonData))
  101. if err := publisher.Send(msg); err != nil {
  102. log.Printf("ZMQ send error: %v", err)
  103. continue
  104. }
  105. eventCount++
  106. if *debug {
  107. log.Printf("[%s] %s", topic, string(jsonData))
  108. } else if eventCount%100 == 0 {
  109. log.Printf("Published %d probe requests", eventCount)
  110. }
  111. }
  112. }