scapy icon indicating copy to clipboard operation
scapy copied to clipboard

Enhancement: efficient round-tripping through machine representation

Open nwf-msr opened this issue 2 years ago • 0 comments

Brief description

I am using scapy as an EDSL for describing packets to be fed through my own custom "dissector" of sorts. Said dissector needs access to computed fields, as well as specified ones, and computed fields are computed only when going to machine representation (AFAICT?). To make this fly, I am specifying packets using Python classes (Ether()/IP()/TCP()/...), converting them to machine representation, and then converting back to the class-ful representation for subsequent processing.

Unfortunately, some of my packets are, shall we say, "weird", by design, in a way that scapy's internal logic for layer binding does not (and probably should not be asked to) understand, and so this round-trip results in a very confused output. I have figured out a way around this -- a way to ensure that the input and output layer stacks have the same classes in the same order -- but it's not particularly pleasant and, worse, it's quadratic in the length of the packet, which is not ideal. A better way to round-trip like this would be most welcome.

Scapy version

2.5.0

Python version

3.11.2

Operating system

5.15.90

Additional environment information

No response

How to reproduce

The round-trip method I've written is as follows:

def scapy_roundtrip(pkt):
  out = pkt.__class__(bytes(pkt))
  layers_left = pkt.layers()[1:]

  cursor = out
  while layers_left != []:
    if not isinstance(cursor.payload, layers_left[0]):
      cursor.decode_payload_as(layers_left[0])

    layers_left = layers_left[1:]
    cursor = cursor.payload
  return out

In the best case, this is just a linear zip down the layers of both the input and output packets. In the worst case, though, every layer of the output needs to be revisited, and decode_payload_as will decode not just that layer but all internal ones as well, leading to quadratic behavior. Ideally, it would be possible to extract just one layer with a guaranteed Raw payload, or something like that, so that decoding was once again linear. Perhaps a flag to decode_payload_as to ignore all layer bindings?

Actual result

No response

Expected result

No response

Related resources

No response

nwf-msr avatar Jul 12 '23 02:07 nwf-msr