66# scapy.contrib.description = HSFZ - BMW High-Speed-Fahrzeug-Zugang
77# scapy.contrib.status = loads
88import logging
9- import struct
109import socket
10+ import struct
1111import time
12-
13- from scapy .contrib .automotive import log_automotive
14- from scapy .packet import Packet , bind_layers , bind_bottom_up
15- from scapy .fields import IntField , ShortEnumField , XByteField
16- from scapy .layers .inet import TCP
17- from scapy .supersocket import StreamSocket
18- from scapy .contrib .automotive .uds import UDS , UDS_TP
19- from scapy .data import MTU
20-
2112from typing import (
2213 Any ,
2314 Optional ,
2819 Union ,
2920)
3021
22+ from scapy .contrib .automotive import log_automotive
23+ from scapy .contrib .automotive .uds import UDS , UDS_TP
24+ from scapy .data import MTU
25+ from scapy .fields import (IntField , ShortEnumField , XByteField ,
26+ ConditionalField , StrFixedLenField )
27+ from scapy .layers .inet import TCP , UDP
28+ from scapy .packet import Packet , bind_layers , bind_bottom_up
29+ from scapy .supersocket import StreamSocket
3130
3231"""
3332BMW HSFZ (High-Speed-Fahrzeug-Zugang / High-Speed-Car-Access).
3433BMW specific diagnostic over IP protocol implementation.
3534The physical interface for this connection is called ENET.
3635"""
3736
37+
3838# #########################HSFZ###################################
3939
4040
4141class HSFZ (Packet ):
42+ control_words = {
43+ 0x01 : "diagnostic_req_res" ,
44+ 0x02 : "acknowledge_transfer" ,
45+ 0x10 : "terminal15" ,
46+ 0x11 : "vehicle_ident_data" ,
47+ 0x12 : "alive_check" ,
48+ 0x13 : "status_data_inquiry" ,
49+ 0x40 : "incorrect_tester_address" ,
50+ 0x41 : "incorrect_control_word" ,
51+ 0x42 : "incorrect_format" ,
52+ 0x43 : "incorrect_dest_address" ,
53+ 0x44 : "message_too_large" ,
54+ 0x45 : "diag_app_not_ready" ,
55+ 0xFF : "out_of_memory"
56+ }
4257 name = 'HSFZ'
4358 fields_desc = [
4459 IntField ('length' , None ),
45- ShortEnumField ('type' , 1 , {0x01 : "message" ,
46- 0x02 : "echo" }),
47- XByteField ('src' , 0 ),
48- XByteField ('dst' , 0 ),
60+ ShortEnumField ('control' , 1 , control_words ),
61+ ConditionalField (
62+ XByteField ('source' , 0 ), lambda p : p .control == 1 ),
63+ ConditionalField (
64+ XByteField ('target' , 0 ), lambda p : p .control == 1 ),
65+ ConditionalField (
66+ StrFixedLenField ("identification_string" ,
67+ None , None , lambda p : p .length ),
68+ lambda p : p .control == 0x11 )
4969 ]
5070
5171 def hashret (self ):
5272 # type: () -> bytes
53- hdr_hash = struct .pack ("B" , self .src ^ self .dst )
73+ hdr_hash = struct .pack ("B" , self .source ^ self .target )
5474 pay_hash = self .payload .hashret ()
5575 return hdr_hash + pay_hash
5676
@@ -71,6 +91,11 @@ def post_build(self, pkt, pay):
7191bind_bottom_up (TCP , HSFZ , sport = 6801 )
7292bind_bottom_up (TCP , HSFZ , dport = 6801 )
7393bind_layers (TCP , HSFZ , sport = 6801 , dport = 6801 )
94+
95+ bind_bottom_up (UDP , HSFZ , sport = 6811 )
96+ bind_bottom_up (UDP , HSFZ , dport = 6811 )
97+ bind_layers (UDP , HSFZ , sport = 6811 , dport = 6811 )
98+
7499bind_layers (HSFZ , UDS )
75100
76101
@@ -111,11 +136,11 @@ def recv(self, x=MTU, **kwargs):
111136
112137
113138class UDS_HSFZSocket (HSFZSocket ):
114- def __init__ (self , src , dst , ip = '127.0.0.1' , port = 6801 , basecls = UDS ):
139+ def __init__ (self , source , target , ip = '127.0.0.1' , port = 6801 , basecls = UDS ):
115140 # type: (int, int, str, int, Type[Packet]) -> None
116141 super (UDS_HSFZSocket , self ).__init__ (ip , port )
117- self .src = src
118- self .dst = dst
142+ self .source = source
143+ self .target = target
119144 self .basecls = HSFZ
120145 self .outputcls = basecls
121146
@@ -128,7 +153,7 @@ def send(self, x):
128153
129154 try :
130155 return super (UDS_HSFZSocket , self ).send (
131- HSFZ (src = self .src , dst = self .dst ) / x )
156+ HSFZ (source = self .source , target = self .target ) / x )
132157 except Exception as e :
133158 # Workaround:
134159 # This catch block is currently necessary to detect errors
@@ -153,7 +178,7 @@ def recv(self, x=MTU, **kwargs):
153178
154179def hsfz_scan (ip , # type: str
155180 scan_range = range (0x100 ), # type: Iterable[int]
156- src = 0xf4 , # type: int
181+ source = 0xf4 , # type: int
157182 timeout = 0.1 , # type: Union[int, float]
158183 verbose = True # type: bool
159184 ):
@@ -166,7 +191,7 @@ def hsfz_scan(ip, # type: str
166191
167192 :param ip: IPv4 address of target to scan
168193 :param scan_range: Range for HSFZ destination address
169- :param src : HSFZ source address, used during the scan
194+ :param source : HSFZ source address, used during the scan
170195 :param timeout: Timeout for each request
171196 :param verbose: Show information during scan, if True
172197 :return: A list of open UDS_HSFZSockets
@@ -175,7 +200,7 @@ def hsfz_scan(ip, # type: str
175200 log_automotive .setLevel (logging .DEBUG )
176201 results = list ()
177202 for i in scan_range :
178- with UDS_HSFZSocket (src , i , ip ) as sock :
203+ with UDS_HSFZSocket (source , i , ip ) as sock :
179204 try :
180205 resp = sock .sr1 (UDS () / UDS_TP (),
181206 timeout = timeout ,
@@ -184,8 +209,8 @@ def hsfz_scan(ip, # type: str
184209 results .append ((i , resp ))
185210 if resp :
186211 log_automotive .debug (
187- "Found endpoint %s, src =0x%x, dst =0x%x" % (ip , src , i ))
212+ "Found endpoint %s, source =0x%x, target =0x%x" % (ip , source , i ))
188213 except Exception as e :
189214 log_automotive .exception (
190215 "Error %s at destination address 0x%x" % (e , i ))
191- return [UDS_HSFZSocket (0xf4 , dst , ip ) for dst , _ in results ]
216+ return [UDS_HSFZSocket (0xf4 , target , ip ) for target , _ in results ]
0 commit comments