mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
new: implemented can.dup and can.dump.inject to read a candump log file
This commit is contained in:
parent
840f819484
commit
7702207ee9
4 changed files with 108 additions and 14 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -14,4 +14,5 @@ stage/
|
|||
|
||||
/snap
|
||||
.idea
|
||||
/cover.out
|
||||
/cover.out
|
||||
/can-data
|
|
@ -2,6 +2,7 @@ package can
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/bettercap/bettercap/v2/session"
|
||||
|
@ -13,6 +14,8 @@ type CANModule struct {
|
|||
session.SessionModule
|
||||
|
||||
deviceName string
|
||||
dumpName string
|
||||
dumpInject bool
|
||||
transport string
|
||||
filter string
|
||||
filterExpr *bexpr.Evaluator
|
||||
|
@ -30,6 +33,8 @@ func NewCanModule(s *session.Session) *CANModule {
|
|||
filterExpr: nil,
|
||||
transport: "can",
|
||||
deviceName: "can0",
|
||||
dumpName: "",
|
||||
dumpInject: false,
|
||||
}
|
||||
|
||||
mod.AddParam(session.NewStringParameter("can.device",
|
||||
|
@ -37,6 +42,15 @@ func NewCanModule(s *session.Session) *CANModule {
|
|||
"",
|
||||
"CAN-bus device."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("can.dump",
|
||||
mod.dumpName,
|
||||
"",
|
||||
"Load CAN traffic from this candump log file."))
|
||||
|
||||
mod.AddParam(session.NewBoolParameter("can.dump.inject",
|
||||
fmt.Sprintf("%v", mod.dumpInject),
|
||||
"Write CAN traffic read form the candump log file to the selected can.device."))
|
||||
|
||||
mod.AddParam(session.NewStringParameter("can.transport",
|
||||
mod.transport,
|
||||
"",
|
||||
|
@ -53,18 +67,6 @@ func NewCanModule(s *session.Session) *CANModule {
|
|||
return mod.Start()
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("can.load_dbc PATH", "",
|
||||
"Start CAN-bus discovery.",
|
||||
func(args []string) error {
|
||||
return mod.Start()
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("can.dbc.load NAME", "can.dbc.load (.+)",
|
||||
"Load a DBC file from the list of available ones or from disk.",
|
||||
func(args []string) error {
|
||||
return mod.dbcLoad(args[0])
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("can.recon off", "",
|
||||
"Stop CAN-bus discovery.",
|
||||
func(args []string) error {
|
||||
|
@ -84,6 +86,12 @@ func NewCanModule(s *session.Session) *CANModule {
|
|||
return mod.Show()
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("can.dbc.load NAME", "can.dbc.load (.+)",
|
||||
"Load a DBC file from the list of available ones or from disk.",
|
||||
func(args []string) error {
|
||||
return mod.dbcLoad(args[0])
|
||||
}))
|
||||
|
||||
mod.AddHandler(session.NewModuleHandler("can.inject FRAME_EXPRESSION", `(?i)^can\.inject\s+([a-fA-F0-9#R]+)$`,
|
||||
"Parse FRAME_EXPRESSION as 'id#data' and inject it as a CAN frame.",
|
||||
func(args []string) error {
|
||||
|
|
76
modules/can/can_dump_reader.go
Normal file
76
modules/can/can_dump_reader.go
Normal file
|
@ -0,0 +1,76 @@
|
|||
package can
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"github.com/evilsocket/islazy/str"
|
||||
"go.einride.tech/can"
|
||||
)
|
||||
|
||||
// (1700623093.260875) can0 7E0#0322128C00000000
|
||||
var dumpLineParser = regexp.MustCompile(`(?m)^\(([\d\.]+)\)\s+([^\s]+)\s+(.+)`)
|
||||
|
||||
type dumpEntry struct {
|
||||
Time string
|
||||
Device string
|
||||
Frame string
|
||||
}
|
||||
|
||||
func (mod *CANModule) startDumpReader() error {
|
||||
mod.Info("loading CAN dump from %s ...", mod.dumpName)
|
||||
|
||||
file, err := os.Open(mod.dumpName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
entries := make([]dumpEntry, 0)
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
line := str.Trim(scanner.Text())
|
||||
if line != "" {
|
||||
if m := dumpLineParser.FindStringSubmatch(line); len(m) != 4 {
|
||||
mod.Warning("unexpected line: '%s' -> %d matches", line, len(m))
|
||||
} else {
|
||||
entries = append(entries, dumpEntry{
|
||||
Time: m[1],
|
||||
Device: m[2],
|
||||
Frame: m[3],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mod.Info("loaded %d entries from candump log", len(entries))
|
||||
|
||||
go func() {
|
||||
mod.Info("candump reader started ...")
|
||||
|
||||
for _, entry := range entries {
|
||||
frame := can.Frame{}
|
||||
if err := frame.UnmarshalString(entry.Frame); err != nil {
|
||||
mod.Error("could not unmarshal CAN frame: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if mod.dumpInject {
|
||||
if err := mod.send.TransmitFrame(context.Background(), frame); err != nil {
|
||||
mod.Error("could not send CAN frame: %v", err)
|
||||
}
|
||||
} else {
|
||||
mod.onFrame(frame)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -25,6 +25,10 @@ func (mod *CANModule) Configure() error {
|
|||
return session.ErrAlreadyStarted(mod.Name())
|
||||
} else if err, mod.deviceName = mod.StringParam("can.device"); err != nil {
|
||||
return err
|
||||
} else if err, mod.dumpName = mod.StringParam("can.dump"); err != nil {
|
||||
return err
|
||||
} else if err, mod.dumpInject = mod.BoolParam("can.dump.inject"); err != nil {
|
||||
return err
|
||||
} else if err, mod.transport = mod.StringParam("can.transport"); err != nil {
|
||||
return err
|
||||
} else if mod.transport != "can" && mod.transport != "udp" {
|
||||
|
@ -43,10 +47,15 @@ func (mod *CANModule) Configure() error {
|
|||
if mod.conn, err = socketcan.Dial(mod.transport, mod.deviceName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mod.recv = socketcan.NewReceiver(mod.conn)
|
||||
mod.send = socketcan.NewTransmitter(mod.conn)
|
||||
|
||||
if mod.dumpName != "" {
|
||||
if err = mod.startDumpReader(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue