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.