I'm trying to implement a custom Packet
type for scapy. My Problem is that I need BitField
s with a dynamic width depending of another field in the packet:
class CustomPacket(Packet):
name="CustomPacket"
fields_desc = [
BitField("bitstring", 0, 8),
BitField("offsets",0, length_from=xxx),
BitField("_padding",0, length_from=xxx), # to make the whole pkt byte aligned
]
The length should depend on how much 1 are in the 8bit bitstring
field.
I tried it with StrLenField
but that didn't work as the length_from function returns the length in byte not bit, as I understand it:
class CustomPacket(Packet):
name = "CustomPacket"
offset_len = 6 # each offset part in the whole string shall be 6 bits long, e.g.
bitstring_len = 8
fields_desc = [
BitField("bitstring", 0, bitstring_len),
StrLenField(
"offsetstring",
0,
length_from=lambda pkt: pkt._calculate_amount_of_offsets(),
),
StrLenField(
"_padding", 0, length_from=lambda pkt: pkt._calculate_needed_padding()
),
]
def _calculate_amount_of_offsets(self):
bits = "{0:08b}".format(self.bitstring)
bits = [int(bit) for bit in list(bits)]
return sum(bits) * self.offset_len
def _calculate_needed_padding(self):
offset_len = self._calculate_amount_of_offsets()
if remainder:= offset_len % 8 != 0:
return 8 - remainder
else:
return remainder
# necessary for show2()
def extract_padding(self, p):
return "", p
Maybe I can somehow create a own FieldType, but I don't get how I can specify a length function there.
The name is terrible because it says Fixed
where it's actually not fixed, but you can use BitFixedLenField
: https://scapy.readthedocs.io/en/latest/api/scapy.fields.html#scapy.fields.BitFixedLenField for this purpose.