Skip to content

automotive, j1939: scanning for CAs - #5164

Open
BenGardiner wants to merge 24 commits into
secdev:masterfrom
BenGardiner:j1939-soft-sockets-again
Open

BenGardiner wants to merge 24 commits into
secdev:masterfrom
BenGardiner:j1939-soft-sockets-again

Conversation

@BenGardiner

@BenGardiner BenGardiner commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Description

This adds j1939 scanning for Controller Applications on-top-of the soft socket support.

The changes aim to introduce only those J1939 value enumeration definitions which can be sourced from freely available locations on the internet. As such, there is not a complete list of the values.

I don't intend any impacts on other parts of the libraries.

fixes missing sr1() functionality in J1939 soft socket on master

LLM coding tools were used in the development of this PR: copilot and gemini, various models.

@BenGardiner

Copy link
Copy Markdown
Contributor Author

@polybassa

Comment thread scapy/contrib/automotive/j1939/__init__.py Outdated
Comment thread scapy/contrib/automotive/j1939/__init__.py
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_dm_scanner.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_name.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_name.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_scanner.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_scanner.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_scanner.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_scanner.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_scanner.py Outdated
Comment thread scapy/contrib/automotive/j1939/j1939_scanner.py Outdated
@BenGardiner

Copy link
Copy Markdown
Contributor Author

thanks @polybassa for the review. I can do almost all of that right now. There's a couple things that are either answering your questions or require me to ask you questions first.

@BenGardiner
BenGardiner force-pushed the j1939-soft-sockets-again branch from fbcb5a9 to 4757249 Compare September 14, 2026 13:12
@BenGardiner

Copy link
Copy Markdown
Contributor Author

I noticed that in the rebase of the scanner code to your replacement soft socket the scanners were no longer cleanly relying on sr() / sr1() via answers() logic. I'll work on bringing that back, fixing the things above I didn't have questions about and then refactoring the scanners to use the answers() logic...

@BenGardiner
BenGardiner force-pushed the j1939-soft-sockets-again branch 3 times, most recently from 97acab8 to f664c8a Compare September 17, 2026 09:58
@BenGardiner

Copy link
Copy Markdown
Contributor Author

Hi @polybassa while I think this is ready for your next review, it might not be merged in this form. There are 'Feature' commits and then 'fixes' on them. e.g. FFfffFffFfffffFfff. To merge you would probably want the fixes squashed into the features. You may even want one squashed commit -- in which case you might consider merging the first commit separately since it is implementing missing sr1() functionality in the current J1939SoftSocket on master.

@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.15483% with 163 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.13%. Comparing base (7d69454) to head (4d7cb29).

Files with missing lines Patch % Lines
scapy/contrib/automotive/j1939/j1939_name.py 66.66% 78 Missing ⚠️
scapy/contrib/automotive/j1939/j1939_scanner.py 87.28% 68 Missing ⚠️
scapy/contrib/automotive/j1939/j1939_dm.py 86.74% 11 Missing ⚠️
scapy/contrib/automotive/j1939/j1939_dm_scanner.py 96.69% 4 Missing ⚠️
scapy/contrib/j1939.py 97.97% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #5164      +/-   ##
==========================================
- Coverage   80.36%   80.13%   -0.24%     
==========================================
  Files         375      380       +5     
  Lines       97675    98770    +1095     
==========================================
+ Hits        78499    79149     +650     
- Misses      19176    19621     +445     
Files with missing lines Coverage Δ
scapy/contrib/automotive/j1939/__init__.py 100.00% <100.00%> (ø)
scapy/layers/can.py 93.12% <100.00%> (+0.04%) ⬆️
scapy/contrib/j1939.py 90.69% <97.97%> (+0.85%) ⬆️
scapy/contrib/automotive/j1939/j1939_dm_scanner.py 96.69% <96.69%> (ø)
scapy/contrib/automotive/j1939/j1939_dm.py 86.74% <86.74%> (ø)
scapy/contrib/automotive/j1939/j1939_scanner.py 87.28% <87.28%> (ø)
scapy/contrib/automotive/j1939/j1939_name.py 66.66% <66.66%> (ø)

... and 20 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@BenGardiner
BenGardiner force-pushed the j1939-soft-sockets-again branch 2 times, most recently from 9d0e0d6 to 3b5967c Compare September 17, 2026 11:31
…allback (heuristic)

Implement answers(), clone_with(), and copy() on J1939 to support sr1()
for directed and broadcast requests with session tracking and fallback
heuristics.

Add identifier property and setter to J1939_CAN to satisfy the CAN
interface for python-can backends, and add a defensive fallback in
_can_send() converting to CAN on AttributeError.

AI-Assisted: yes (Gemini 3.8 Flash)
Adds a scanner to identify Controller Appliactions in a J1939 network,
various scanning techniques are provided including both broadcast and
unicast.

AI-Assisted: yes (Gemini 3.8 Flash)
Shorten verbose docstring in _pre_probe_flush per review comment by
@polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
…efinitions

Define CAN_EFF_FLAG in scapy.layers.can and use it in j1939_sa_filter.
Build UDS TesterPresent and XCP CONNECT probe payloads using UDS,
ISOTP, and XCP layer definitions with lazy importing per review comments
by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
…ddress discrimination test

In test_j1939_scan_uds_and_xcp_src_addr_discrimination, replace pre-injected
replies with a responder thread on a paired socket so responses are sent
dynamically in response to queries for each scanner source address.

AI-Assisted: yes (Gemini 3.8 Flash)
… CA scanner

Address review comments from @polybassa:
- Use generic CANSocket instead of NativeCANSocket in socket resolution.
- Standardize scanner signatures to accept a live socket as the mandatory
  first argument and an optional reconnect socket factory callable.

AI-Assisted: yes (Gemini 3.8 Flash)
…es to prefix convention

Per review comments by @polybassa:
- Rename automotive log_j1939 export to j1939_log.
- Add j1939_ prefixed aliases for pgn_from_fields, dst_from_fields, and pgn_is_pdu1.

AI-Assisted: yes (Gemini 3.8 Flash)
…_size in J1939_DTC

Use negative tot_size and end_tot_size on BitFields for J1939_DTC
to decode little-endian bit fields natively, removing manual
do_dissect and do_build byte-reversal overrides per review comment
by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
Replace manual dtcs list handling, custom __init__, do_dissect, and
do_build in J1939_DM1 with PacketListField and post_build per review
comment by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
…39_DM13

Remove the unused _hold_signal_enum dictionary from J1939_DM13 and add a
test verifying it is not present per review comment by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
Convert DmScanResult to a dataclass and add unit test verifying
it is a dataclass per review comment by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
…9_DM1

Verify that J1939_DM1 inherits Packet.__repr__ and does not override it,
per review comment by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
Remove post_build padding in J1939_DM1 and add a test verifying it is
not present, per review comment by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
…J1939_DM1

Verify that J1939_DM1 does not override do_build per review comment
by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
… scanner

Add TP.CM BAM and RTS frame detection to j1939_scan_dm_pgn() and abort
incoming RTS sessions to release ECU state.

AI-Assisted: yes (Gemini 3.8 Flash)
… DM and DM scanner

Address review comments from @polybassa:
- Pass socket directly to sniff_dm1 to avoid creation and destruction overhead.
- Support socket instance in send_dm14_request.
- Standardize DM scanner signatures to accept a live socket as the mandatory
  first argument and an optional reconnect socket factory callable.

AI-Assisted: yes (Gemini 3.8 Flash)
…rialization, and response matching

Add J1939Request, serialize requested PGN from stacked diagnostic layers,
preserve stacked payload in _payload_of(), and expand answers() to match
request layers, acknowledgments, and DM14/DM15 pairs.

AI-Assisted: yes (Gemini 3.8 Flash)
…_size in J1939_NAME

Use negative tot_size and end_tot_size on BitFields for J1939_NAME
to decode little-endian bit fields natively, removing manual
do_dissect and do_build byte-reversal overrides per review comment
by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
Convert J1939NameResult to a dataclass and add unit tests
verifying it per review comments by @polybassa.

AI-Assisted: yes (Gemini 3.8 Flash)
… NAME request functions

Address review comments from @polybassa:
- Standardize NAME request functions to accept an optional reconnect
  socket factory callable.

AI-Assisted: yes (Gemini 3.8 Flash)
…de_name

Per review comments by @polybassa:
- Rename decode_j1939_name to j1939_decode_name to match prefix convention.

AI-Assisted: yes (Gemini 3.8 Flash)
@BenGardiner
BenGardiner force-pushed the j1939-soft-sockets-again branch from 3b5967c to 4d7cb29 Compare September 17, 2026 12:41
@BenGardiner

Copy link
Copy Markdown
Contributor Author

I'm going to look closer at https://github.com/secdev/scapy/actions/runs/35222531093/job/105206012569?pr=5164 -- that seems like there could be something wrong with the soft socket...

@BenGardiner

Copy link
Copy Markdown
Contributor Author

I'm going to look closer at https://github.com/secdev/scapy/actions/runs/35222531093/job/105206012569?pr=5164 -- that seems like there could be something wrong with the soft socket...

yep that was a race in close() of the soft socket -- just like we had in isotp soft socket.

I have a fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants