diff --git a/capture/collector.go b/capture/collector.go index c99cb35..a4ac35e 100644 --- a/capture/collector.go +++ b/capture/collector.go @@ -95,6 +95,7 @@ func (coll *Collector) parser() { log.Warnf("unable to unmarshal request from %s: %s", obj.Address.String(), err) continue } + log.Debugf("recv[%s]: %s", obj.Address, msg.String()) response, err := coll.handler(obj.Address, msg) if err != nil { log.Warnf("unable to handle request from %s: %s", obj.Address.String(), err) @@ -108,6 +109,7 @@ func (coll *Collector) parser() { // SendTo a specifical address func (coll *Collector) SendTo(addr *net.UDPAddr, msg *data.SocketMSG) { + log.Debugf("send[%s]: %s", addr, msg.String()) data, err := msg.Marshal() if err != nil { log.Warnf("unable to marshal response for %s: %s", addr.String(), err) @@ -125,6 +127,7 @@ func (coll *Collector) SendTo(addr *net.UDPAddr, msg *data.SocketMSG) { // Send to every connection to default address func (coll *Collector) Send(msg *data.SocketMSG) { + log.Debugf("send: %s", msg.String()) data, err := msg.Marshal() if err != nil { log.Warnf("unable to marshal response: %s", err) diff --git a/cmd/controller.go b/cmd/controller.go new file mode 100644 index 0000000..c2c70b2 --- /dev/null +++ b/cmd/controller.go @@ -0,0 +1,67 @@ +package cmd + +import ( + "os" + "os/signal" + "strings" + "syscall" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + + "dev.sum7.eu/wifictld/analyzer/capture" + "dev.sum7.eu/wifictld/analyzer/controller" + "dev.sum7.eu/wifictld/analyzer/database" +) + +var ( + central bool +) + +// queryCmd represents the query command +var controllerCmd = &cobra.Command{ + Use: "controller ", + Short: "simulate a wifictld controller", + Example: `analyzer controller "eth0,wlan0"`, + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + ifaces := strings.Split(args[0], ",") + + log.Infof("listen on: %s", ifaces) + + var ifacesConfigs []capture.IFaceConfig + for _, iface := range ifaces { + ifaceConfig := capture.IFaceConfig{ + InterfaceName: iface, + Port: port, + IPAddress: ipAddress, + } + ifacesConfigs = append(ifacesConfigs, ifaceConfig) + } + + db := database.NewDB() + + ctr := controller.NewController(db, central) + defer ctr.Close() + + coll := capture.NewCollector(ctr.Handler, ifacesConfigs) + defer coll.Close() + + ctr.Send = coll.Send + ctr.SendTo = coll.SendTo + + // Wait for INT/TERM + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + sig := <-sigs + log.Println("received", sig) + + }, +} + +func init() { + RootCmd.AddCommand(controllerCmd) + controllerCmd.Flags().IntVar(&port, "port", capture.Port, "define a port to listen (if not set or set to 0 the kernel will use a random free port at its own)") + controllerCmd.Flags().StringVar(&ipAddress, "listen", capture.MulticastAddressDefault, "") + controllerCmd.Flags().BoolVar(¢ral, "central", false, "") +} diff --git a/cmd/dump.go b/cmd/dump.go index 50553f4..5c89624 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -40,6 +40,8 @@ var dumpCmd = &cobra.Command{ ifacesConfigs = append(ifacesConfigs, ifaceConfig) } + data.DEBUG = debug + coll := capture.NewCollector(func(addr *net.UDPAddr, msg *data.SocketMSG) (*data.SocketMSG, error) { log.Infof("recv[%s]: %s", addr, msg.String()) return nil, nil diff --git a/controller/handler.go b/controller/handler.go new file mode 100644 index 0000000..ac0e04a --- /dev/null +++ b/controller/handler.go @@ -0,0 +1,29 @@ +package controller + +import ( + "net" + + // log "github.com/sirupsen/logrus" + + "dev.sum7.eu/wifictld/analyzer/data" +) + +func (c *Controller) Handler(addr *net.UDPAddr, msg *data.SocketMSG) (*data.SocketMSG, error) { + ignore := false + if msg.Types.Is(data.SocketMSGTypeClient) && msg.Client != nil { + ignore = c.db.LearnClient(addr.IP, msg.Client) + } + if !msg.Types.Is(data.SocketMSGTypeRequest) { + return nil, nil + } + + msg = &data.SocketMSG{ + Types: (data.SocketMSGTypeResponse | data.SocketMSGTypeClient), + Client: c.db.GetClient(msg.Client.Addr), + } + + if c.central || !ignore { + return msg, nil + } + return nil, nil +} diff --git a/controller/main.go b/controller/main.go new file mode 100644 index 0000000..8334fed --- /dev/null +++ b/controller/main.go @@ -0,0 +1,39 @@ +package controller + +import ( + "net" + "time" + + log "github.com/sirupsen/logrus" + + "dev.sum7.eu/wifictld/analyzer/data" + "dev.sum7.eu/wifictld/analyzer/database" +) + +type Controller struct { + SendTo func(addr *net.UDPAddr, msg *data.SocketMSG) + Send func(msg *data.SocketMSG) + db *database.DB + ticker *time.Ticker + central bool +} + +func NewController(db *database.DB, central bool) *Controller { + ctl := &Controller{ + ticker: time.NewTicker(60 * time.Second), + db: db, + central: central, + } + go ctl.Repeated() + return ctl +} + +func (c *Controller) Close() { + c.ticker.Stop() +} + +func (c *Controller) Repeated() { + for range c.ticker.C { + log.Infof("lerned: %d APs, %d Clients", len(c.db.APs), len(c.db.Clients)) + } +} diff --git a/data/socket_msg.go b/data/socket_msg.go index 6d7ead9..3a99527 100644 --- a/data/socket_msg.go +++ b/data/socket_msg.go @@ -9,6 +9,8 @@ import ( log "github.com/sirupsen/logrus" ) +var DEBUG = false + // SocketMSGType kind of packages type SocketMSGType uint32 @@ -20,7 +22,10 @@ const ( ) func (a SocketMSGType) Is(b SocketMSGType) bool { - log.Debugf("SocketType: %x & %x = %x -> %b", a, b, (a & b), (a&b) > 0) + if DEBUG { + + log.Debugf("SocketType: %x & %x = %x -> %b", a, b, (a & b), (a&b) > 0) + } return (a & b) > 0 } @@ -84,7 +89,9 @@ func (msg *SocketMSG) Marshal() ([]byte, error) { } func (msg *SocketMSG) Unmarshal(obj []byte) error { - log.Debugf("hex unmarshal: %x", obj) + if DEBUG { + log.Debugf("hex unmarshal: %x", obj) + } pos := 0 diff --git a/database/ap.go b/database/ap.go new file mode 100644 index 0000000..ccfb583 --- /dev/null +++ b/database/ap.go @@ -0,0 +1,4 @@ +package database + +type AP struct { +} diff --git a/database/client.go b/database/client.go new file mode 100644 index 0000000..8baf11b --- /dev/null +++ b/database/client.go @@ -0,0 +1,60 @@ +package database + +import ( + "net" + "time" + + // log "github.com/sirupsen/logrus" + + "dev.sum7.eu/wifictld/analyzer/data" +) + +type Client struct { + Addr net.HardwareAddr + Time time.Time + TryProbe uint16 + TryAuth uint16 + Connected bool + Authed bool + FreqHighest uint16 + SignalLowFreq int16 + SignalHighFreq int16 +} + +func (db *DB) LearnClient(apIP net.IP, clientWifictl *data.WifiClient) bool { + ret := false + + apAddr := apIP.String() + ap, ok := db.APs[apAddr] + if !ok { + ap = &AP{} + db.APs[apAddr] = ap + } + clientAddr := clientWifictl.Addr.String() + client, ok := db.Clients[clientAddr] + if !ok { + client = &Client{ + Addr: clientWifictl.Addr, + } + db.Clients[clientAddr] = client + } + client.Time = time.Now() + + if client.FreqHighest < clientWifictl.FreqHighest { + ret = (client.FreqHighest != 0) + client.FreqHighest = clientWifictl.FreqHighest + } + return ret +} + +func (db *DB) GetClient(addr net.HardwareAddr) *data.WifiClient { + client, ok := db.Clients[addr.String()] + wClient := &data.WifiClient{ + Addr: addr, + Time: time.Now(), + } + if ok { + wClient.TryProbe = client.TryProbe + } + return wClient +} diff --git a/database/main.go b/database/main.go new file mode 100644 index 0000000..222a96b --- /dev/null +++ b/database/main.go @@ -0,0 +1,13 @@ +package database + +type DB struct { + Clients map[string]*Client `json:"client"` + APs map[string]*AP `json:"ap"` +} + +func NewDB() *DB { + return &DB{ + Clients: make(map[string]*Client), + APs: make(map[string]*AP), + } +}