Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions scapy/contrib/isotp/isotp_packet.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,8 @@
# scapy.contrib.description = ISO-TP (ISO 15765-2) Packet Definitions
# scapy.contrib.status = library

import struct
import logging

from scapy.config import conf
from scapy.packet import Packet
from scapy.fields import BitField, FlagsField, StrLenField, \
ThreeBytesField, XBitField, ConditionalField, \
BitEnumField, ByteField, XByteField, BitFieldLenField, StrField, \
FieldLenField, IntField, ShortField
from scapy.compat import chb, orb
from scapy.layers.can import CAN, CAN_FD_MAX_DLEN as CAN_FD_MAX_DLEN
from scapy.error import Scapy_Exception

import struct
# Typing imports
from typing import (
Optional,
Expand All @@ -29,6 +18,16 @@
cast,
)

from scapy.compat import chb, orb
from scapy.config import conf
from scapy.error import Scapy_Exception
from scapy.fields import BitField, FlagsField, StrLenField, \
ThreeBytesField, XBitField, ConditionalField, \
BitEnumField, ByteField, XByteField, BitFieldLenField, StrField, \
FieldLenField, IntField, ShortField
from scapy.layers.can import CAN, CAN_FD_MAX_DLEN as CAN_FD_MAX_DLEN, CANFD
from scapy.packet import Packet

log_isotp = logging.getLogger("scapy.contrib.isotp")

CAN_MAX_IDENTIFIER = (1 << 29) - 1 # Maximum 29-bit identifier
Expand Down Expand Up @@ -103,6 +102,7 @@ def fragment(self, *args, **kargs):
"""

fd = kargs.pop("fd", False)
pkt_cls = CANFD if fd else CAN

def _get_data_len():
# type: () -> int
Expand All @@ -122,10 +122,10 @@ def _get_data_len():
frame_data = struct.pack('B', self.rx_ext_address) + frame_data

if self.rx_id is None or self.rx_id <= 0x7ff:
pkt = CAN(identifier=self.rx_id, data=frame_data)
pkt = pkt_cls(identifier=self.rx_id, data=frame_data)
else:
pkt = CAN(identifier=self.rx_id, flags="extended",
data=frame_data)
pkt = pkt_cls(identifier=self.rx_id, flags="extended",
data=frame_data)
return [pkt]

# Construct the first frame
Expand All @@ -138,10 +138,10 @@ def _get_data_len():
idx = _get_data_len() - len(frame_header)
frame_data = self.data[0:idx]
if self.rx_id is None or self.rx_id <= 0x7ff:
frame = CAN(identifier=self.rx_id, data=frame_header + frame_data)
frame = pkt_cls(identifier=self.rx_id, data=frame_header + frame_data)
else:
frame = CAN(identifier=self.rx_id, flags="extended",
data=frame_header + frame_data)
frame = pkt_cls(identifier=self.rx_id, flags="extended",
data=frame_header + frame_data)

# Construct consecutive frames
n = 1
Expand All @@ -156,10 +156,10 @@ def _get_data_len():
if self.rx_ext_address:
frame_header = struct.pack('B', self.rx_ext_address) + frame_header # noqa: E501
if self.rx_id is None or self.rx_id <= 0x7ff:
pkt = CAN(identifier=self.rx_id, data=frame_header + frame_data) # noqa: E501
pkt = pkt_cls(identifier=self.rx_id, data=frame_header + frame_data) # noqa: E501
else:
pkt = CAN(identifier=self.rx_id, flags="extended",
data=frame_header + frame_data)
pkt = pkt_cls(identifier=self.rx_id, flags="extended",
data=frame_header + frame_data)
pkts.append(pkt)
return cast(List[Packet], pkts)

Expand Down
44 changes: 23 additions & 21 deletions scapy/contrib/isotp/isotp_soft_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,16 @@
# Copyright (C) Nils Weiss <[email protected]>
# Copyright (C) Enrico Pozzobon <[email protected]>

import heapq
# scapy.contrib.description = ISO-TP (ISO 15765-2) Soft Socket Library
# scapy.contrib.status = library
import logging
import socket
import struct
import time
import traceback
import heapq
import socket

from threading import Thread, Event, RLock
from bisect import bisect_left

from scapy.packet import Packet
from scapy.layers.can import CAN
from scapy.error import Scapy_Exception
from scapy.supersocket import SuperSocket
from scapy.config import conf
from scapy.consts import LINUX
from scapy.utils import EDecimal
from scapy.automaton import ObjectPipe, select_objects
from scapy.contrib.isotp.isotp_packet import ISOTP, CAN_MAX_DLEN, N_PCI_SF, \
N_PCI_CF, N_PCI_FC, N_PCI_FF, ISOTP_MAX_DLEN, ISOTP_MAX_DLEN_2015, CAN_FD_MAX_DLEN

from threading import Thread, Event, RLock
# Typing imports
from typing import (
Optional,
Expand All @@ -40,6 +27,17 @@
TYPE_CHECKING,
)

from scapy.automaton import ObjectPipe, select_objects
from scapy.config import conf
from scapy.consts import LINUX
from scapy.contrib.isotp.isotp_packet import ISOTP, CAN_MAX_DLEN, N_PCI_SF, \
N_PCI_CF, N_PCI_FC, N_PCI_FF, ISOTP_MAX_DLEN, ISOTP_MAX_DLEN_2015, CAN_FD_MAX_DLEN
from scapy.error import Scapy_Exception
from scapy.layers.can import CAN, CANFD
from scapy.packet import Packet
from scapy.supersocket import SuperSocket
from scapy.utils import EDecimal

if TYPE_CHECKING:
from scapy.contrib.cansocket import CANSocket

Expand Down Expand Up @@ -209,8 +207,10 @@ def select(sockets, remain=None):
"""This function is called during sendrecv() routine to wait for
sockets to be ready to receive
"""
obj_pipes = [x.impl.rx_queue for x in sockets if
isinstance(x, ISOTPSoftSocket) and not x.closed]
obj_pipes: List[Union[SuperSocket, ObjectPipe[Tuple[bytes, Union[float, EDecimal]]]]] = [ # noqa: E501
x.impl.rx_queue for x in sockets if
isinstance(x, ISOTPSoftSocket) and not x.closed]
obj_pipes += [x for x in sockets if isinstance(x, ObjectPipe) and not x.closed]

ready_pipes = select_objects(obj_pipes, remain)

Expand Down Expand Up @@ -579,13 +579,15 @@ def _get_padding_size(pl_size):
return fd_accepted_sizes[-1]
return fd_accepted_sizes[pos]

pkt_cls = CANFD if self.fd else CAN

if self.padding:
load += b"\xCC" * (_get_padding_size(len(load)) - len(load))
if self.tx_id is None or self.tx_id <= 0x7ff:
self.can_socket.send(CAN(identifier=self.tx_id, data=load))
self.can_socket.send(pkt_cls(identifier=self.tx_id, data=load))
else:
self.can_socket.send(CAN(identifier=self.tx_id, flags="extended",
data=load))
self.can_socket.send(pkt_cls(identifier=self.tx_id, flags="extended",
data=load))

def can_recv(self):
# type: () -> None
Expand Down
23 changes: 17 additions & 6 deletions test/contrib/isotp_soft_socket.uts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ with TestSocket(CANFD) as cans, TestSocket(CANFD) as stim, ISOTPSoftSocket(cans,
s.failure_analysis()
raise Scapy_Exception("ERROR")
msg = pkts[0]
assert msg.data == dhex(data_str)
assert dhex(data_str) in msg.data

= Two frame receive

Expand Down Expand Up @@ -235,7 +235,8 @@ def testfd():
cfs = stim.sniff(timeout=20, count=len(fragments) - 1,
started_callback=lambda: stim.send(ack))
for fragment, cf in zip(fragments, ff + cfs):
assert (bytes(fragment) == bytes(cf))
print(bytes(fragment), bytes(cf))
assert (bytes(fragment) in bytes(cf))

testfd()

Expand Down Expand Up @@ -370,7 +371,7 @@ with TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x2
assert can[0].data == dhex("10 {} {}".format("%02X" % size_to_send, " ".join(["%02X" % x for x in range(max_pl_size)])))
can = cans.sniff(timeout=1, count=1, started_callback=lambda: cans.send(CANFD(identifier = 0x241, data=dhex("30 00 00"))))
assert can[0].identifier == 0x641
assert can[0].data == dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)])))
assert dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)]))) in can[0].data

= Send single frame ISOTP message
with TestSocket(CAN) as cans, TestSocket(CAN) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x241) as s:
Expand Down Expand Up @@ -468,7 +469,7 @@ with TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x2
raise Scapy_Exception("ERROR")
can = pkts[0]
assert can.identifier == 0x641
assert can.data == dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)])))
assert dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)]))) in can.data

thread.join(15)
acks.close()
Expand Down Expand Up @@ -557,7 +558,7 @@ with TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x2
raise Scapy_Exception("ERROR")
can = pkts[0]
assert can.identifier == 0x641
assert can.data == dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)])))
assert dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)]))) in can.data

thread.join(15)
acks.close()
Expand Down Expand Up @@ -644,7 +645,7 @@ with TestSocket(CANFD) as isocan, ISOTPSoftSocket(isocan, tx_id=0x641, rx_id=0x2
raise Scapy_Exception("ERROR")
can = pkts[0]
assert can.identifier == 0x641
assert can.data == dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)])))
assert dhex("21 {}".format(" ".join(["%02X" % x for x in range(max_pl_size, size_to_send)]))) in can.data

thread.join(15)
acks.close()
Expand Down Expand Up @@ -943,6 +944,16 @@ assert rx == msg
assert rx2 is not None
assert rx2 == msg

= ISOTPSoftSocket sr1 timeout
msg = ISOTP(b'\x11\x22\x33\x11\x22\x33\x11\x22\x33\x11\x22\x33')

with TestSocket(CAN) as isocan_tx, ISOTPSoftSocket(isocan_tx, 0x123, 0x321) as sock_tx, \
TestSocket(CAN) as isocan_rx, ISOTPSoftSocket(isocan_rx, 0x321, 0x123) as sock_rx:
isocan_rx.pair(isocan_tx)
rx2 = sock_tx.sr1(msg, timeout=1, verbose=True)

assert rx2 is None

= ISOTPSoftSocket sniff

msg = ISOTP(b'\x11\x22\x33\x11\x22\x33\x11\x22\x33\x11\x22\x33')
Expand Down
Loading