main.go 3.2 KB

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