Automotive

can-utils

can-utils is the Linux command-line toolkit for the CAN bus, built on the kernel’s SocketCAN framework. It’s a family of small, sharp tools: candump shows you every frame on the bus, cansend transmits a single frame, canplayer replays a captured log, cangen generates traffic for testing, and cansniffer gives a live, diff-highlighted view that makes it easy to spot which message changes when you press a button in the car. Together they’re how you read, record, and reproduce CAN traffic from the terminal.

Official-repo package; Security → Automotive → can-utils. It provides around thirty tools, including the ISO-TP and J1939 helpers for higher-level protocols.

Two of the core tools

candump — watch traffic on the bus:

candump: invalid option -- '-'
candump - dump CAN bus traffic.

Usage: candump [options] <CAN interface>+
  (use CTRL-C to terminate candump)

Options:
         -t <type>   (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)
         -H          (read hardware timestamps instead of system timestamps)
         -c          (increment color mode level)
         -i          (binary output - may exceed 80 chars/line)
         -a          (enable additional ASCII output)
         -S          (swap byte order in printed CAN data[] - marked with '`' )
         -s <level>  (silent mode - 0: off (default) 1: animation 2: silent)
         -l          (log CAN-frames into file. Sets '-s 2' by default)
         -f <fname>  (log CAN-frames into file <fname>. Sets '-s 2' by default)
         -L          (use log file format on stdout)
         -n <count>  (terminate after reception of <count> CAN frames)
         -r <size>   (set socket receive buffer to <size>)
         -D          (Don't exit if a "detected" can device goes down)
         -d          (monitor dropped CAN frames)
         -e          (dump CAN error frames in human-readable format)
         -8          (display raw DLC values in {} for Classical CAN)
         -x          (print extra message infos, rx/tx brs esi)
         -T <msecs>  (terminate after <msecs> if no frames were received)

Up to 16 CAN interfaces with optional filter sets can be specified
on the commandline in the form: <ifname>[,filter]*

Filters:
  Comma separated filters can be specified for each given CAN interface:
    <can_id>:<can_mask>
         (matches when <received_can_id> & mask == can_id & mask)
    <can_id>~<can_mask>
         (matches when <received_can_id> & mask != can_id & mask)
    #<error_mask>
         (set error frame filter, see include/linux/can/error.h)
    [j|J]
         (join the given CAN filters - logical AND semantic)

CAN IDs, masks and data content are given and expected in hexadecimal values.
When the can_id is 8 digits long the CAN_EFF_FLAG is set for 29 bit EFF format.
Without any given filter all data frames are received ('0:0' default filter).

Use interface name 'any' to receive from all CAN interfaces.

Examples:
candump -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8

candump -l any,0~0,#FFFFFFFF
         (log only error frames but no(!) data frames)
candump -l any,0:0,#FFFFFFFF
         (log error frames and also all data frames)
candump vcan2,12345678:DFFFFFFF
         (match only for extended CAN ID 12345678)
candump vcan2,123:7FF
         (matches CAN ID 123 - including EFF and RTR frames)
candump vcan2,123:C00007FF
         (matches CAN ID 123 - only SFF and non-RTR frames)

cansend — transmit a frame:

cansend - send CAN-frames via CAN_RAW sockets.

Usage: cansend <device> <can_frame>.

<can_frame>:
 <can_id>#{data}          for CAN CC (Classical CAN 2.0B) data frames
 <can_id>#R{len}          for CAN CC (Classical CAN 2.0B) data frames
 <can_id>#{data}_{dlc}    for CAN CC (Classical CAN 2.0B) data frames
 <can_id>#R{len}_{dlc}    for CAN CC (Classical CAN 2.0B) data frames
 <can_id>##<flags>{data}  for CAN FD frames
 <vcid><prio>#<flags>:<sdt>:<af>#<data> for CAN XL frames

<can_id>:
 3 (SFF) or 8 (EFF) hex chars
{data}:
 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.')
{len}:
 an optional 0..8 value as RTR frames can contain a valid dlc field
_{dlc}:
 an optional 9..F data length code value when payload length is 8
<flags>:
 a single ASCII Hex value (0 .. F) which defines canfd_frame.flags

<vcid>:
 2 hex chars - virtual CAN network identifier (00 .. FF)
<prio>:
 3 hex chars - 11 bit priority value (000 .. 7FF)
<flags>:
 2 hex chars values (00 .. FF) which defines canxl_frame.flags
<sdt>:
 2 hex chars values (00 .. FF) which defines canxl_frame.sdt
<af>:
 8 hex chars - 32 bit acceptance field (canxl_frame.af)
<data>:
 1..2048 ASCII hex-values (optionally separated by '.')

Examples:
  5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / 123##1 / 213##311223344 /
  1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E /
  45123#81:00:12345678#11223344.556677 / 00242#81:07:40000123#112233

Examples

# Bring up a CAN interface (adjust bitrate to the bus)
sudo ip link set can0 up type can bitrate 500000

# Dump everything on the bus
candump can0

# Live diff view — highlights the bytes that change (great for finding a signal)
cansniffer can0

# Send a single frame (id 123, 8 data bytes)
cansend can0 123#DEADBEEF00000000

# Record traffic, then replay it later
candump -l can0            # writes candump-<date>.log
canplayer -I candump-*.log

The usual reverse-engineering loop: run cansniffer, operate a control in the car (a door lock, a light), watch which message changes, then replay or craft that message with cansend. For a visual version of the same workflow, use SavvyCAN.