Skip to content

Commit

Permalink
Fix recv of HSFZ and DoIP (#4053)
Browse files Browse the repository at this point in the history
* Fix recv of HSFZ and DoIP

* add unit test for hsfz

* add test case for DoIP
  • Loading branch information
polybassa committed Jul 8, 2023
1 parent 66fdfa3 commit 6dbdc37
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 0 deletions.
21 changes: 21 additions & 0 deletions scapy/contrib/automotive/bmw/hsfz.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,27 @@ def __init__(self, ip='127.0.0.1', port=6801):
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.connect((self.ip, self.port))
StreamSocket.__init__(self, s, HSFZ)
self.buffer = b""

def recv(self, x=MTU):
# type: (int) -> Optional[Packet]
if self.buffer:
len_data = self.buffer[:4]
else:
len_data = self.ins.recv(4, socket.MSG_PEEK)
if len(len_data) != 4:
return None

len_int = struct.unpack(">I", len_data)[0]
len_int += 6
self.buffer += self.ins.recv(len_int - len(self.buffer))

if len(self.buffer) != len_int:
return None

pkt = self.basecls(self.buffer) # type: Packet
self.buffer = b""
return pkt


class UDS_HSFZSocket(HSFZSocket):
Expand Down
21 changes: 21 additions & 0 deletions scapy/contrib/automotive/doip.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,33 @@ def __init__(self, ip='127.0.0.1', port=13400, activate_routing=True,
self.ip = ip
self.port = port
self.source_address = source_address
self.buffer = b""
self._init_socket()

if activate_routing:
self._activate_routing(
source_address, target_address, activation_type, reserved_oem)

def recv(self, x=MTU):
# type: (int) -> Optional[Packet]
if self.buffer:
len_data = self.buffer[:8]
else:
len_data = self.ins.recv(8, socket.MSG_PEEK)
if len(len_data) != 8:
return None

len_int = struct.unpack(">I", len_data[4:8])[0]
len_int += 8
self.buffer += self.ins.recv(len_int - len(self.buffer))

if len(self.buffer) != len_int:
return None

pkt = self.basecls(self.buffer) # type: Packet
self.buffer = b""
return pkt

def _init_socket(self, sock_family=socket.AF_INET):
# type: (int) -> None
s = socket.socket(sock_family, socket.SOCK_STREAM)
Expand Down
29 changes: 29 additions & 0 deletions test/contrib/automotive/bmw/hsfz.uts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,32 @@ assert pkt.dst == 0x10
assert pkt.type == 1
assert pkt.securitySeed == b"0" * 0xfff00

= Test HSFZSocket


server_up = threading.Event()
def server():
buffer = bytes(HSFZ(type=1, src=0xf4, dst=0x10) / Raw(b'\x11\x22\x33' * 1024))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 6801))
sock.listen(1)
server_up.set()
connection, address = sock.accept()
connection.send(buffer[:1024])
time.sleep(0.1)
connection.send(buffer[1024:])
connection.close()
finally:
sock.close()

server_thread = threading.Thread(target=server)
server_thread.start()
server_up.wait(timeout=1)
sock = HSFZSocket()

pkts = sock.sniff(timeout=1, count=1)
assert len(pkts) == 1
assert len(pkts[0]) > 2048
27 changes: 27 additions & 0 deletions test/contrib/automotive/doip.uts
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,30 @@ assert req.hashret() == resp.hashret()
# exclude TCP layer from answers check
assert resp[3].answers(req[3])
assert not req[3].answers(resp[3])

= Test DoIPSocket

server_up = threading.Event()
def server():
buffer = b'\x02\xfd\x80\x02\x00\x00\x00\x05\x00\x00\x00\x00\x00\x02\xfd\x80\x01\x00\x00\x00\n\x10\x10\x0e\x80P\x03\x002\x01\xf4'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 13400))
sock.listen(1)
server_up.set()
connection, address = sock.accept()
connection.send(buffer)
connection.close()
finally:
sock.close()


server_thread = threading.Thread(target=server)
server_thread.start()
server_up.wait(timeout=1)
sock = DoIPSocket(activate_routing=False)

pkts = sock.sniff(timeout=1, count=2)
assert len(pkts) == 2

0 comments on commit 6dbdc37

Please sign in to comment.