Add single layer UDS configuration mode#31
Conversation
- Add split_layers import and orb from scapy.compat - Add 'single_layer_UDS': False to default UDS contribs config - Add _uds_service_cls dict and dispatch_hook classmethod to UDS to support direct dispatch in single layer mode - Add _uds_service(service_id) class decorator that: - Prepends a conditional 'service' field (shown only in single layer mode) - Registers the class in UDS._uds_service_cls dispatch table - Binds the layer to UDS in multi-layer mode - Injects a hashret for single layer mode - Add uds_single_layer_mode(enable) function to toggle modes at runtime - Replace all 55 bind_layers(UDS, ...) calls with @_uds_service(...) decorators Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
- Use len(_pkt) >= 1 instead of truthiness check in dispatch_hook - Add comment explaining _sid closure variable captures by value Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/8125374f-f4ee-41eb-b908-21bc9363a30f Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/8125374f-f4ee-41eb-b908-21bc9363a30f Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/98843579-9ca6-43b4-958a-457a46b29a63 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
…anges Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/84433859-6054-4e3c-a058-5bd51c1fcb56 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/6cbead0f-e508-411e-a433-5ba980dfbc5d Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
…yer_mode; use config directly Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/68821df8-a572-42b8-a882-d8026ab945fc Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
…of helper functions Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/68821df8-a572-42b8-a882-d8026ab945fc Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
…ery service packet Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/5dbfa702-3238-4f56-9d29-7868afb27512 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
| (0x7F, OBD_NR), | ||
| ] | ||
|
|
||
| for _sid, _cls in _OBD_SERVICES: |
There was a problem hiding this comment.
Modify the obd service packets explicitly
There was a problem hiding this comment.
Done in a8f05e9. Replaced the loop with an explicit block for each OBD service class — fields_desc prepend, bind_layers, and _service_cls registration are now written out individually for all 19 service classes.
polybassa
left a comment
There was a problem hiding this comment.
make the OBD Service modifications explicitly
…stead of loop Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/c30eedc4-0783-44f0-86b8-2a0dcdf0fb75 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Done in a8f05e9 — each OBD service class now has its |
| @@ -0,0 +1,35 @@ | |||
| # SPDX-License-Identifier: GPL-2.0-only | |||
There was a problem hiding this comment.
Deleted in c137bec — utils.py has been removed entirely.
| The same API is available for the other protocols — use the ``single_layer_mode`` | ||
| config key in the corresponding ``conf.contribs`` entry: | ||
|
|
||
| +----------+-----------------------------------------------+ |
There was a problem hiding this comment.
Simplified in c137bec — replaced the per-protocol table with a single-line note: "The same single_layer_mode key works for all protocols: replace 'UDS' with 'KWP', 'OBD', or 'GMLAN' as appropriate." Also removed the bullet-point explanation and the reference to the deleted automotive.utils module.
| return struct.pack('B', self.requestServiceId & ~0x40) | ||
| return struct.pack('B', self.service & ~0x40) | ||
|
|
||
| _service_cls = {} # type: ignore |
There was a problem hiding this comment.
provide the proper type: Dict[int, Type[Packet]]
There was a problem hiding this comment.
Fixed in c137bec — _service_cls = {} # type: Dict[int, Type[Packet]] in gmlan.py (and same correction applied to uds.py and kwp.py). Type added to from typing imports in all three files; a from typing block was also added to gmlan.py which had none.
| return cls | ||
|
|
||
|
|
||
| OBD_S01.fields_desc = [ |
There was a problem hiding this comment.
modify the code where the packet is defined initially. not here
There was a problem hiding this comment.
Done in c137bec — _OBD_SERVICES dict and _obd_slm function are now defined in services.py. Each OBD service class (OBD_S01, OBD_S02, OBD_S03, OBD_S03_PR, OBD_S04, OBD_S04_PR, OBD_S06, OBD_S07, OBD_S07_PR, OBD_S08, OBD_S09, OBD_S0A, OBD_S0A_PR, OBD_NR) has the ConditionalField directly in its fields_desc. The PR classes in pid/pids.py, iid/iids.py, mid/mids.py, tid/tids.py import _OBD_SERVICES and _obd_slm from services.py and also have the field inline. obd.py now only does bind_layers + _service_cls registration — no post-definition fields_desc manipulation.
| bind_layers(OBD, OBD_S01, service=0x01) | ||
| OBD._service_cls[0x01] = OBD_S01 | ||
|
|
||
| OBD_S02.fields_desc = [ |
| fields_desc = [ | ||
| ConditionalField( | ||
| XByteEnumField('service', 0xa9, GMLAN.services), | ||
| lambda pkt: conf.contribs['GMLAN'].get('single_layer_mode', False)), |
There was a problem hiding this comment.
globally define the lambda as function and reuse it. Try to make a one-liner
There was a problem hiding this comment.
apply for all other conditional fields
There was a problem hiding this comment.
Done in c137bec — defined _uds_slm, _kwp_slm, _gmlan_slm, and _obd_slm as module-level named functions; all 134 ConditionalField calls across UDS (55), KWP (53), GMLAN (26) are now one-liners, e.g. ConditionalField(XByteEnumField('service', 0x10, UDS.services), _uds_slm).
…unctions, OBD ConditionalField in class bodies, simplify doc Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/ce2f23f8-7fa9-462b-b281-7165aad3cb78 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
…r mode Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/d5e15641-5fee-4efa-8436-1e172bb245e4 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
…n tests Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/d5e15641-5fee-4efa-8436-1e172bb245e4 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
| assert len(log) == 2 | ||
| assert log[1] == "0x80" | ||
| assert log[0] == "DeviceControlPositiveResponse" No newline at end of file | ||
| assert log[0] == "DeviceControlPositiveResponse" |
There was a problem hiding this comment.
Some unit tests still fail, for example:
Single layer GMLAN mode
###(073)=[failed] Single layer mode: sub-subpacket bindings are unaffected
Fix this one in the CI
There was a problem hiding this comment.
Fixed in ea02c8f. The 6-byte test data b'\x52\x01\x00\x01\x02\x03' left only 3 bytes for GMLAN_DTC (which needs 4), causing a dissection exception when conf.debug_dissector = True is active in CI (set globally by uds.py). Changed to b'\x52\x01\x00\x01\x02\x03\x04' (7 bytes) so the full GMLAN_DTC (failureRecordNumber + DTCHighByte + DTCLowByte + DTCFailureType) is valid.
…n SLM mode Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/987a3bb3-9f72-440b-8b2d-7e36a911bb39 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Agent-Logs-Url: https://github.com/polybassa/scapy-1/sessions/7880b535-39ac-4795-83a2-06408efc1460 Co-authored-by: polybassa <1676055+polybassa@users.noreply.github.com>
Fixed in b8ed598:
All four test suites still pass (UDS 185/185, GMLAN 85/85, KWP 85/85, OBD 107/107). |
compatibility_mode: Trueto config init in uds.py, kwp.py, gmlan.py, obd.py_uds_slm,_kwp_slm,_gmlan_slm,_obd_slmfunctions to check compatibility_mode_kwp_slmtype annotation (Any→Packet)Packetimport in obd.py