4141 _SocketUnion , _TransitionTuple , StateGenerator
4242from scapy .contrib .automotive .uds import UDS , UDS_NR , UDS_DSC , UDS_TP , \
4343 UDS_RDBI , UDS_WDBI , UDS_SA , UDS_RC , UDS_IOCBI , UDS_RMBA , UDS_ER , \
44- UDS_TesterPresentSender , UDS_CC , UDS_RDBPI , UDS_RD , UDS_TD
44+ UDS_TesterPresentSender , UDS_CC , UDS_RDBPI , UDS_RD , UDS_TD , UDS_DSCPR
4545# TODO: Refactor this import
4646from scapy .contrib .automotive .uds_ecu_states import * # noqa: F401, F403
4747from scapy .error import Scapy_Exception
@@ -89,7 +89,8 @@ class UDS_DSCEnumerator(UDS_Enumerator, StateGeneratingServiceEnumerator):
8989 _supported_kwargs .update ({
9090 'delay_state_change' : (int , lambda x : x >= 0 ),
9191 'overwrite_timeout' : (bool , None ),
92- 'close_socket_when_entering_session_2' : (bool , None )
92+ 'close_socket_when_entering_session_2' : (bool , None ),
93+ 'support_suppress_positive_response' : (bool , None )
9394 })
9495 _supported_kwargs ["scan_range" ] = (
9596 (list , tuple , range ), lambda x : max (x ) < 0x100 and min (x ) >= 0 )
@@ -113,7 +114,13 @@ class UDS_DSCEnumerator(UDS_Enumerator, StateGeneratingServiceEnumerator):
113114 This enumerator will close the socket
114115 if session 2 (ProgrammingSession)
115116 was entered, if True. This will
116- force a reconnect by the executor."""
117+ force a reconnect by the executor.
118+ :param bool support_suppress_positive_response: False by default.
119+ If True, this enumerator will treat
120+ no response for a DSC request with a
121+ session type > 0x80 as a positive
122+ response and will therefore create a
123+ new state with a session value - 0x80."""
117124
118125 def _get_initial_requests (self , ** kwargs ):
119126 # type: (Any) -> Iterable[Packet]
@@ -172,6 +179,29 @@ def get_new_edge(self,
172179 except KeyError :
173180 close_socket = False
174181
182+ try :
183+ support_out_of_spec = config [UDS_DSCEnumerator .__name__ ]["support_suppress_positive_response" ] # noqa: E501
184+ except KeyError :
185+ support_out_of_spec = False
186+
187+ if edge is None :
188+ try :
189+ state , req , resp , _ , _ = cast (ServiceEnumerator , self ).results [- 1 ] # noqa: E501
190+ except IndexError :
191+ return None
192+
193+ if support_out_of_spec and resp is None and req .diagnosticSessionType > 0x80 : # noqa: E501
194+ resp = UDS () / UDS_DSCPR (diagnosticSessionType = 0x80 - req .diagnosticSessionType ) # noqa: E501
195+ new_state = EcuState .get_modified_ecu_state (resp , req , state )
196+ if new_state == state :
197+ return None
198+ else :
199+ edge = (state , new_state )
200+ self ._edge_requests [edge ] = req
201+ return edge
202+ else :
203+ return None
204+
175205 if edge :
176206 state , new_state = edge
177207 # Force TesterPresent if session is changed
@@ -1210,8 +1240,7 @@ def _random_memory_addr_pkt(addr_len=None): # noqa: E501
12101240 pkt .memorySizeLen = random .randint (1 , 4 )
12111241 pkt .memoryAddressLen = addr_len or random .randint (1 , 4 )
12121242 UDS_RMBARandomEnumerator .set_size (pkt , 0x10 )
1213- addr = random .randint (0 , 2 ** (8 * pkt .memoryAddressLen ) - 1 ) & \
1214- (0xffffffff << (4 * pkt .memoryAddressLen ))
1243+ addr = random .randint (0 , 2 ** (8 * pkt .memoryAddressLen ) - 1 ) & (0xffffffff << (4 * pkt .memoryAddressLen )) # noqa: E501
12151244 UDS_RMBARandomEnumerator .set_addr (pkt , addr )
12161245 return pkt
12171246
0 commit comments