Skip to content

Commit

Permalink
ISOTPNativeSocket improvements (#4363)
Browse files Browse the repository at this point in the history
  • Loading branch information
polybassa committed May 14, 2024
1 parent b44f9a2 commit fa94fe3
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 31 deletions.
73 changes: 44 additions & 29 deletions scapy/contrib/isotp/isotp_native_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,44 +319,59 @@ def __init__(self,
raise Scapy_Exception("Provide a string or a CANSocket "
"object as iface parameter")

self.iface = cast(str, iface) or conf.contribs['NativeCANSocket']['iface'] # noqa: E501
self.can_socket = socket.socket(socket.PF_CAN, socket.SOCK_DGRAM,
CAN_ISOTP)
self.__set_option_flags(self.can_socket,
ext_address,
rx_ext_address,
listen_only,
padding,
frame_txtime)

self.iface: str = cast(str, iface) or conf.contribs['NativeCANSocket']['iface'] # noqa: E501
# store arguments internally
self.tx_id = tx_id
self.rx_id = rx_id
self.ext_address = ext_address
self.rx_ext_address = rx_ext_address

self.can_socket.setsockopt(SOL_CAN_ISOTP,
CAN_ISOTP_RECV_FC,
self.__build_can_isotp_fc_options(
stmin=stmin, bs=bs))
self.can_socket.setsockopt(SOL_CAN_ISOTP,
CAN_ISOTP_LL_OPTS,
self.__build_can_isotp_ll_options(
mtu=CAN_ISOTP_CANFD_MTU if fd
else CAN_ISOTP_DEFAULT_LL_MTU,
tx_dl=CAN_FD_ISOTP_DEFAULT_LL_TX_DL if fd
else CAN_ISOTP_DEFAULT_LL_TX_DL))
self.can_socket.setsockopt(
self.bs = bs
self.stmin = stmin
self.padding = padding
self.listen_only = listen_only
self.frame_txtime = frame_txtime
self.fd = fd
if basecls is None:
log_isotp.warning('Provide a basecls ')
self.basecls = basecls
self._init_socket()

def _init_socket(self) -> None:
can_socket = socket.socket(socket.PF_CAN, socket.SOCK_DGRAM,
CAN_ISOTP)
self.__set_option_flags(can_socket,
self.ext_address,
self.rx_ext_address,
self.listen_only,
self.padding,
self.frame_txtime)

can_socket.setsockopt(SOL_CAN_ISOTP,
CAN_ISOTP_RECV_FC,
self.__build_can_isotp_fc_options(
stmin=self.stmin, bs=self.bs))
can_socket.setsockopt(SOL_CAN_ISOTP,
CAN_ISOTP_LL_OPTS,
self.__build_can_isotp_ll_options(
mtu=CAN_ISOTP_CANFD_MTU if self.fd
else CAN_ISOTP_DEFAULT_LL_MTU,
tx_dl=CAN_FD_ISOTP_DEFAULT_LL_TX_DL if self.fd
else CAN_ISOTP_DEFAULT_LL_TX_DL))
can_socket.setsockopt(
socket.SOL_SOCKET,
SO_TIMESTAMPNS,
1
)

self.__bind_socket(self.can_socket, self.iface, tx_id, rx_id)
self.ins = self.can_socket
self.outs = self.can_socket
if basecls is None:
log_isotp.warning('Provide a basecls ')
self.basecls = basecls
self.__bind_socket(can_socket, self.iface, self.tx_id, self.rx_id)
# make sure existing sockets are closed,
# required in case of a reconnect.
self.closed = False
self.close()

self.ins = can_socket
self.outs = can_socket
self.closed = False

def recv_raw(self, x=0xffff):
# type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]] # noqa: E501
Expand Down
1 change: 1 addition & 0 deletions scapy/contrib/isotp/isotp_soft_socket.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
Callable,
TYPE_CHECKING,
)

if TYPE_CHECKING:
from scapy.contrib.cansocket import CANSocket

Expand Down
35 changes: 33 additions & 2 deletions scapy/supersocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ def __init__(self,

def send(self, x):
# type: (Packet) -> int
"""Sends a `Packet` object
:param x: `Packet` to be send
:return: Number of bytes that have been sent
"""
sx = raw(x)
try:
x.sent_time = time.time()
Expand All @@ -116,14 +121,23 @@ def send(self, x):
if WINDOWS:
def _recv_raw(self, sock, x):
# type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]]
"""Internal function to receive a Packet"""
"""Internal function to receive a Packet.
:param sock: Socket object from which data are received
:param x: Number of bytes to be received
:return: Received bytes, address information and no timestamp
"""
pkt, sa_ll = sock.recvfrom(x)
return pkt, sa_ll, None
else:
def _recv_raw(self, sock, x):
# type: (socket.socket, int) -> Tuple[bytes, Any, Optional[float]]
"""Internal function to receive a Packet,
and process ancillary data.
:param sock: Socket object from which data are received
:param x: Number of bytes to be received
:return: Received bytes, address information and an optional timestamp
"""
timestamp = None
if not self.auxdata_available:
Expand Down Expand Up @@ -172,11 +186,22 @@ def _recv_raw(self, sock, x):

def recv_raw(self, x=MTU):
# type: (int) -> Tuple[Optional[Type[Packet]], Optional[bytes], Optional[float]] # noqa: E501
"""Returns a tuple containing (cls, pkt_data, time)"""
"""Returns a tuple containing (cls, pkt_data, time)
:param x: Maximum number of bytes to be received, defaults to MTU
:return: A tuple, consisting of a Packet type, the received data,
and a timestamp
"""
return conf.raw_layer, self.ins.recv(x), None

def recv(self, x=MTU, **kwargs):
# type: (int, **Any) -> Optional[Packet]
"""Receive a Packet according to the `basecls` of this socket
:param x: Maximum number of bytes to be received, defaults to MTU
:return: The received `Packet` object, or None
"""
cls, val, ts = self.recv_raw(x)
if not val or not cls:
return None
Expand All @@ -200,6 +225,8 @@ def fileno(self):

def close(self):
# type: () -> None
"""Gracefully close this socket
"""
if self.closed:
return
self.closed = True
Expand All @@ -213,11 +240,15 @@ def close(self):

def sr(self, *args, **kargs):
# type: (Any, Any) -> Tuple[SndRcvList, PacketList]
"""Send and Receive multiple packets
"""
from scapy import sendrecv
return sendrecv.sndrcv(self, *args, **kargs)

def sr1(self, *args, **kargs):
# type: (Any, Any) -> Optional[Packet]
"""Send one packet and receive one answer
"""
from scapy import sendrecv
ans = sendrecv.sndrcv(self, *args, **kargs)[0] # type: SndRcvList
if len(ans) > 0:
Expand Down

0 comments on commit fa94fe3

Please sign in to comment.