oremanj/python-netfilterqueue

set_payload() throws TypeError

etkaar opened this issue · 2 comments

After I was able to install NetfilterQueue (see #53), I received a TypeError when using set_payload() after directly changing a payload attribute.

On Debian Stretch this has worked without any problems for years. At this moment I use Debian Buster 10.2, NetfilterQueue 0.8.1, Python 3.7.3 and python3-scapy 2.4.0-2.

pkt = IP(packet.get_payload())
...
pkt[UDP].payload = bytes(response)
...
packet.set_payload(bytes(pkt))

This problem can be fixed using two different ways:

pkt[UDP].remove_payload()
pkt[UDP].add_payload(bytes(response))
pkt[UDP].payload = conf.raw_layer(load=response)
Exception ignored in: 'netfilterqueue.global_callback'
Traceback (most recent call last):
  File "modifier.py", line 117, in modify
    packet.set_payload(bytes(pkt))
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 345, in __bytes__
    return self.build()
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 444, in build
    p = self.do_build()
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 425, in do_build
    self = next(iter(self))
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 819, in loop
    for x in loop(todo[:], done):
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 819, in loop
    for x in loop(todo[:], done):
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 819, in loop
    for x in loop(todo[:], done):
  [Previous line repeated 9 more times]
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 826, in loop
    for payl in payloads:
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 819, in loop
    for x in loop(todo[:], done):
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 819, in loop
    for x in loop(todo[:], done):
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 819, in loop
    for x in loop(todo[:], done):
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 831, in loop
    pkt = self.clone_with(payload=payl, **done2)
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 804, in clone_with
    pkt.add_payload(payload)
  File "/usr/lib/python3/dist-packages/scapy/packet.py", line 188, in add_payload
    raise TypeError("payload must be either 'Packet' or 'bytes', not [%s]" % repr(payload))
TypeError: payload must be either 'Packet' or 'bytes', not [255]

When I remove python3-scapy (2.4.0-2) and update to scapy 2.4.3 via pip3, the error message changes:

Exception ignored in: 'netfilterqueue.global_callback'
Traceback (most recent call last):
  File "modifier.py", line 117, in modify
    packet.set_payload(bytes(pkt))
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 487, in __bytes__
    return self.build()
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 607, in build
    p = self.do_build()
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 588, in do_build
    self = next(iter(self))
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 960, in loop
    for x in loop(todo[:], done):
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 960, in loop
    for x in loop(todo[:], done):
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 960, in loop
    for x in loop(todo[:], done):
  [Previous line repeated 9 more times]
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 968, in loop
    if self.fields == done and payloads.__iterlen__() == 1:
  File "/usr/local/lib/python3.7/dist-packages/scapy/packet.py", line 1023, in __iterlen__
    return length * self.payload.__iterlen__()
AttributeError: 'bytes' object has no attribute '__iterlen__'

I think the problem here is how you are building the packet with Scapy and not the netfilterqueue.
This fails not because set_payload() function of netfilterqueue, but the bytes() of the scapy Packet object:

packet.set_payload(bytes(pkt))

Closing because this is not netfilterqueue's fault.