问题
I'm trying to build PTPv2 protocol using Scapy.
There are few message types in this protocol, so I use ConditionalField
to describe the different fields options:
class PTPv2(Packet):
name = "Precision Time Protocol V2"
fields_desc = [
# Header
BitField('transportSpecific', 1, 4),
BitEnumField('messageType', 0, 4, Message_Types),
ByteField('versionPTP', 2),
LenField('messageLength', None),
ByteField('subdomainNumber', 0),
ByteField('empty1', 0),
XShortField('flags', 0),
LongField('correction', 0),
IntField('empty2', 0),
XLongField('ClockIdentity', 0),
XShortField('SourcePortId', 0),
XShortField('sequenceId', 0),
ByteField('control', 0),
SignedByteField('logMessagePeriod', 0),
# SYNC message, messageType=0
ConditionalField(XBitField('TimestampSec', 0, 48),lambda pkt: pkt.messageType==0),
ConditionalField(IntField('TimestampNanoSec', 0), lambda pkt: pkt.messageType == 0),
# Follow up message, messageType=8
ConditionalField(XBitField('preciseOriginTimestampSec', 0, 48), lambda pkt: pkt.messageType == 8),
ConditionalField(IntField('preciseOriginTimestampNanoSec', 0), lambda pkt: pkt.messageType == 8)
# Path delay resp follow up message, messageType=0xA
ConditionalField(XBitField('responseOriginTimestampSec', 0, 48), lambda pkt: pkt.messageType == 0xA),
ConditionalField(IntField('responseOriginTimestampNanoSec', 0), lambda pkt: pkt.messageType == 0xA),
ConditionalField(XLongField('requestingSourcePortIdentity', 0), lambda pkt: pkt.messageType == 0xA),
ConditionalField(XShortField('requestingSourcePortId', 0), lambda pkt: pkt.messageType == 0xA)
Now, I want the messageLength
field to describe the layer's length, and be calculated automatically, depending on the existing fields.
It should describe the length of all fields in the PTPv2 layer, starting from the first one (transportSpecific
).
I read about PacketLenField
and FieldLenField
, but it seems they both describe the length of one field, not a group of fields (as far as I understand).
I also read about LenField
(which is written as the type in the code), but it calculates the length of the next layers, not the current one (so in this case always gives 0).
Any idea how can I solve this?
Thanks!
回答1:
This is usually done in scapy using the post_build
callback, as so: (you need to add it to your packet)
(Taken from inet6.py)
def post_build(self, p, pay):
# p += pay # if you also want the payload to be taken into account
if self.messageLength is None:
tmp_len = len(p) # edit as you want
p = p[:2] + struct.pack("!H", tmp_len) + p[4:] # Adds length as short on bytes 3-4
return p + pay # edit if previous is changed
You can then use a ByteField/ShortField... accordingly instead of the LenField.
PacketLenField
is when you use a PacketListField
and FieldLenField
is for FieldListField
来源:https://stackoverflow.com/questions/54125711/scapy-layers-length-field