Scapy - поле длины слоя

Я пытаюсь создать протокол PTPv2 с помощью Scapy. В этом протоколе несколько типов сообщений, поэтому я использую ConditionalField для описания различных параметров полей:

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)

Теперь я хочу, чтобы поле messageLength описывало длину слоя и вычислялось автоматически в зависимости от существующих полей. Он должен описывать длину всех полей на уровне PTPv2, начиная с первого (transportSpecific).

Я читал про PacketLenField и FieldLenField, но вроде они оба описывают длину одного поля, а не группы полей (насколько я понимаю).

Еще читал про LenField (что в коде пишется как тип), но он вычисляет длину следующих слоев, а не текущего (поэтому в этом случае всегда дает 0).

Есть идеи, как я могу это решить?

Спасибо!


person Shir    schedule 10.01.2019    source источник


Ответы (1)


Обычно это делается в scapy с помощью обратного вызова post_build, например: (вам нужно добавить его в свой пакет)

(Взято с 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

Затем вы можете использовать ByteField/ShortField... соответственно вместо LenField.

PacketLenField — это когда вы используете PacketListField, а FieldLenField — это FieldListField.

person Cukic0d    schedule 10.01.2019