Use Cases

Aligned fields and padding

There are many different ways those alignments are managed.

Normal length and data, but alignment constraint

In this case, lenfield is the exact length of datafield, or precise enough to deduce it, an can be used to tell data and padding apart. In this case we can consider the padding as not being really part of datafield. For this case, we will create a padfield so that we can access and tweak padding.

class TestPadNormal(Packet):
    fields_desc = [ FieldLenField("lenfield", None, length_of="datafield"),
                    StrLenField("datafield", "defaultval", length_from=lambda pkt:pkt.lenfield),
                    StrFixedLenField("padfield", None, length_from=lambda pkt:-len(pkt.datafield)%8), ]
>>> hexdump(TestPadNormal(datafield="1234")/"XXXX")
0000   00 04 31 32 33 34 00 00  00 00 58 58 58 58         ..1234....XXXX
>>> hexdump(TestPadNormal(datafield="")/"XXXX")
0000   00 00 58 58 58 58                                  ..XXXX
>>> hexdump(TestPadNormal(datafield="1")/"XXXX")
0000   00 01 31 00 00 00 00 00  00 00 58 58 58 58         ..1.......XXXX
>>> hexdump(TestPadNormal(datafield="12")/"XXXX")
0000   00 02 31 32 00 00 00 00  00 00 58 58 58 58         ..12......XXXX
>>> hexdump(TestPadNormal(datafield="1234567")/"XXXX")
0000   00 07 31 32 33 34 35 36  37 00 58 58 58 58         ..1234567.XXXX

Note that the default value of padfield (None) can be "XXXXXXXX" for instance if you want to pad with other things than "\x00".

Weakened length

In this case, lenfield holds a weakened value of the original length, which cannot be recovered. This happens for instance when the datafield 's length is given by 16 bit words. At disassembly, there is no mean to tell data and padding apart. At this point, we can consider that the padding is part of the data. Thus, the solution is to make things so that any user entry into this field is padded.

class TestPadWeak(Packet):
    fields_desc = [ FieldLenField("lenfield", None, length_of="datafield", adjust=lambda pkt,l:(l+1)/2),
                    PadField(StrLenField("datafield", "defaultval", length_from=lambda pkt:pkt.lenfield*2),  2), ]
>>> hexdump(TestPadWeak(datafield="")/"XXXX")
0000   00 00 58 58 58 58                                  ..XXXX
>>> hexdump(TestPadWeak(datafield="1")/"XXXX")
0000   00 01 31 00 58 58 58 58                            ..1.XXXX
>>> hexdump(TestPadWeak(datafield="12")/"XXXX")
0000   00 01 31 32 58 58 58 58                            ..12XXXX
>>> hexdump(TestPadWeak(datafield="123")/"XXXX")
0000   00 02 31 32 33 00 58 58  58 58                     ..123.XXXX

PadField can be given the padwith parameter that will provide the pattern of the padding. For instance: padwith="123" for aligning on 4 bytes with padding ending with "1", "12", or "123".

class TestPadWeak2(Packet):
    fields_desc = [ FieldLenField("lenfield", None, length_of="datafield", adjust=lambda pkt,l:(l+1)/2),
                    PadField(StrLenField("datafield", "defaultval", length_from=lambda pkt:pkt.lenfield*2),  4, padwith="PAD"), ]
>>> hexdump(TestPadWeak2(datafield="")/"XXXX")
0000   00 00 58 58 58 58                                  ..XXXX
>>> hexdump(TestPadWeak2(datafield="1")/"XXXX")
0000   00 01 31 50 41 44 58 58  58 58                     ..1PADXXXX
>>> hexdump(TestPadWeak2(datafield="12")/"XXXX")
0000   00 01 31 32 50 41 58 58  58 58                     ..12PAXXXX
>>> hexdump(TestPadWeak2(datafield="123")/"XXXX")
0000   00 02 31 32 33 50 58 58  58 58                     ..123PXXXX
>>> hexdump(TestPadWeak2(datafield="1234")/"XXXX")
0000   00 02 31 32 33 34 58 58  58 58                     ..1234XXXX