Beispiel #1
0
    def _clone(packet: Packet, name: str) -> None:
        """Replaces the Scapy ``packet`` class by an exact copy.

        This is a trick used when we need to modify a ``Packet`` class attribute
        without affecting all instances of an object.
        For instance, if we change ``fields_desc`` to add a field, all new
        instances will be changed as this is a class attribute.
        
        :param packet: the Scapy Packet to update.
        :param name: the new class name for packet.
        """
        # Checks if a binding exists between packet and its preceding layer
        # (bindings are defined as a list of tuples `layer.payload_guess`)
        in_payload_guess = False
        if packet.underlayer is not None:
            in_payload_guess = any(packet.__class__ in binding \
                                   for binding in packet.underlayer.payload_guess)
        # Duplicates our packet class and replaces it by the clone
        # first checks that provided name is not already used, otherwise generates a new one
        while name in [type(o).__name__ for o in gc.get_objects()]:
            name = name + '_' + str(randint(1000000, 9999999))
        class_copy = type(name, (packet.__class__, ), {})
        packet.__class__ = class_copy
        # Bindings with the preceding layer must be done again
        if in_payload_guess:
            packet.underlayer.payload_guess.insert(0, ({}, packet.__class__))