Manipulation of network packets¶
Network packet manipulation is primarily intended for negative protocol tests and provides the possibility to modify the packets before sending them. The special feature here is, that the protocol implementation including its specified protocol sequences is preserved. This means, for example, that specific responses can be manipulated and be sent at the right moment in order to provoke the desired error case. This is to be clearly distinguished from the manual sending of malformed packets, since with manual sending timing behavior or dynamically set protocol fields are difficult to determine by hand.
Usage of manipulation objects¶
Manipulation of packets is done by manipulation objects. A manipulation object can be a fixed
ByteStream (static manipulation) or a Python callback (dynamic manipulation). Callbacks
can be general python callables, such as functions or objects with a __call__ method.
For a ByteStream the passed ByteStream is used instead of the packet.
In a callback, the manipulation is dynamic: The callback receives the packet object to be
originally sent as an argument and may modify it. The return value can be the modified object or
a mere byte sequence (bytes), which is then used instead of the original object.
If the callback returns None, no network packet will be sent.
Here is an example:
import ...
class SimpleManipulation:
def __call__(self, packet: PacketClass) -> Optional[Union[PacketClass, bytes]]:
packet.SetSomeField(123)
return packet
def EvenSimplerManipulation(packet: PacketClass) -> Optional[Union[PacketClass, bytes]]:
return b'that is easy'
def DoNotSendAnything(packet: PacketClass) -> Optional[Union[PacketClass, bytes]]:
return None
If a callback is used as manipulation object, it must be stored in a python module in a defined subdirectory of user libraries.
After the manipulation has been started with a manipulation object, changes to the object no longer affect the manipulation, since it is copied at startup. However, changes can be made by combining the appropriate jobs to start and stop a manipulation.
To ensure inter-process and inter-network availability of the manipulation object, it is copied
using the Python pickle serialization. In borderline cases the restrictions and special features
of the pickle module have to be considered.
MKA Manipulation¶
Jobs to start and stop the MKA manipulation: StartMkaManipulation and StopMkaManipulation
Packet object: PacketMka
Subdirectory:
MkaManipulationsExample:
from typing import Optional, Union
from tts.lib.ethernet.PacketMka import PacketMka # api.Ethernet not available here
def MyMkaManipulation(packet: PacketMka) -> Optional[Union[PacketMka, bytes]]:
packet.SetKeyServerPriority(42)
packet.SetMemberIdentifier(ByteStream('11:22:33:44:55:66:77:88:99:AA:BB:CC'))
return packet
IKE Manipulation¶
Jobs to start and stop the IKE manipulation: StartIkeManipulation and StopIkeManipulation
Packet object: PacketIke
Subdirectory:
IkeManipulationsExample:
from typing import Optional, Union
from tts.lib.ethernet.PacketIke import PacketIke # api.Ethernet not available here
def MyIkeManipulation(packet: PacketIke) -> Optional[Union[PacketIke, bytes]]:
packet.minorVersion = 12
return packet
SOME/IP-SD Manipulation¶
Jobs to start and stop the SOME/IP-SD manipulation: StartSomeIpSdManipulation and StopSomeIpSdManipulation
Packet object: PacketSomeIpSd
Subdirectory:
SomeIpSdManipulationsExample:
from typing import Optional, Union
from tts.lib.ethernet.PacketSomeIpSd import PacketSomeIpSd # api.Ethernet not available here
def MySomeIpSdManipulation(packet: PacketSomeIpSd) -> Optional[Union[PacketSomeIpSd, bytes]]:
entries = packet.GetEntryList()
for entry in entries:
entry.SetMajorVersion(0xAB)
return packet
SOME/IP Manipulation¶
Jobs to start and stop the SOME/IP manipulation: StartSomeIpManipulation and StopSomeIpManipulation
Packet object: PacketSomeIp
Subdirectory:
SomeIpManipulationsExample:
from typing import Optional, Union
from tts.lib.ethernet.PacketSomeIp import PacketSomeIp # api.Ethernet not available here
def MySomeIpManipulation(packet: PacketSomeIp) -> Optional[Union[PacketSomeIp, bytes]]:
if packet.GetMessageId() == 0x35018002:
packet.SetSessionId(0x0C)
return packet
Using jobs to manipulate the protocol headers¶
After starting a connection via the MKA port or IKEv2 port, packets to be sent, such as UDP packets, contain an additional MACsec or IPsec authentication header that can be manipulated by jobs. This does not affect the internal protocol processes, but the packets to be sent can be changed in a targeted manner. All contents to be changed are given to the job (e.g. StartMacSecManipulation) as parameters and are effective until the associated stop job (e.g. StopMacSecManipulation) is called. The change per Packet remains constant except for change of sequence numbers and ICV.
See StartMacSecManipulation, StopMacSecManipulation, StartAhManipulation, StopAhManipulation
Note: The calls for the jobs to start and stop the manipulation are currently asynchronous. It takes some time for the manipulative effect to set in.