diff --git a/modules/can/can.go b/modules/can/can.go index 370163eb..64346078 100644 --- a/modules/can/can.go +++ b/modules/can/can.go @@ -1,6 +1,7 @@ package can import ( + "errors" "net" "github.com/bettercap/bettercap/session" @@ -18,6 +19,7 @@ type CANModule struct { conn net.Conn recv *socketcan.Receiver + send *socketcan.Transmitter } func NewCanModule(s *session.Session) *CANModule { @@ -68,6 +70,15 @@ func NewCanModule(s *session.Session) *CANModule { return mod.Show() })) + 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 { + if !mod.Running() { + return errors.New("can module not running") + } + return mod.Inject(args[0]) + })) + return mod } diff --git a/modules/can/can_inject.go b/modules/can/can_inject.go new file mode 100644 index 00000000..f7717db0 --- /dev/null +++ b/modules/can/can_inject.go @@ -0,0 +1,24 @@ +package can + +import ( + "context" + + "github.com/dustin/go-humanize" + "go.einride.tech/can" +) + +func (mod *CANModule) Inject(expr string) (err error) { + frame := can.Frame{} + if err := frame.UnmarshalString(expr); err != nil { + return err + } + + mod.Info("injecting %s of CAN frame %d ...", + humanize.Bytes(uint64(frame.Length)), frame.ID) + + if err := mod.send.TransmitFrame(context.Background(), frame); err != nil { + return err + } + + return +} diff --git a/modules/can/can_recon.go b/modules/can/can_recon.go index 75d0c355..fd7ce8e9 100644 --- a/modules/can/can_recon.go +++ b/modules/can/can_recon.go @@ -62,6 +62,7 @@ func (mod *CANModule) Configure() error { } mod.recv = socketcan.NewReceiver(mod.conn) + mod.send = socketcan.NewTransmitter(mod.conn) return nil } @@ -124,6 +125,7 @@ func (mod *CANModule) Stop() error { mod.conn.Close() mod.conn = nil mod.recv = nil + mod.send = nil mod.dbc = nil mod.dbcPath = "" }