Skip to content

Commit 7bf9906

Browse files
committed
Add ConditionalFields for additional message types and update messageLength with post_build func
1 parent 034a49b commit 7bf9906

File tree

1 file changed

+55
-147
lines changed

1 file changed

+55
-147
lines changed

scapy/layers/ptp_v2.py

Lines changed: 55 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
References : IEEE 1588-2008
1010
"""
1111

12+
import struct
13+
1214
from scapy.packet import Packet, bind_layers
1315
from scapy.fields import (
1416
BitEnumField,
@@ -19,8 +21,9 @@
1921
ShortField,
2022
ByteEnumField,
2123
FlagsField,
22-
PacketField,
2324
XLongField,
25+
XByteField,
26+
ConditionalField,
2427
)
2528
from scapy.layers.inet import UDP
2629

@@ -75,64 +78,19 @@
7578
}
7679

7780

78-
class OriginTimestamp(Packet):
79-
name = "originTimestamp"
80-
fields_desc = [
81-
BitField("seconds", 0, 48),
82-
IntField("nanoseconds", 0)
83-
]
84-
85-
86-
class PTPHeader(Packet):
81+
class PTP(Packet):
8782
"""
88-
PTP Header based on IEEE 1588-2008 / Section 13.3.
83+
PTP packet based on IEEE 1588-2008 / Section 13.3
8984
"""
9085

91-
########################################################################################
92-
# IEEE 1588-2008 / Section 13.3 Header / Table 18
93-
########################################################################################
94-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95-
# | Bits | | |
96-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Octets | Offset |
97-
# | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | | |
98-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99-
# | transportSpecific | messageType | 1 | 0 |
100-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101-
# | reserved | versionPTP | 1 | 1 |
102-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103-
# | messageLength | 2 | 2 |
104-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105-
# | domainNumber | 1 | 4 |
106-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107-
# | reserved | 1 | 5 |
108-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
109-
# | flagField | 2 | 6 |
110-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111-
# | correctionField | 8 | 8 |
112-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
113-
# | reserved | 4 | 16 |
114-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115-
# | sourcePortIdentity | 10 | 20 |
116-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117-
# | sequenceId | 2 | 30 |
118-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119-
# | controlField | 1 | 32 |
120-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
121-
# | logMessageInterval | 1 | 33 |
122-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123-
########################################################################################
124-
#
125-
# sourcePortIdentity(10 bytes) contain clockIdentity(8 bytes) and portNumber(2 bytes)
126-
#
127-
128-
name = "PTPHeader"
86+
name = "PTP"
12987
match_subclass = True
13088
fields_desc = [
13189
BitField("transportSpecific", 0, 4),
13290
BitEnumField("messageType", 0x0, 4, _message_type),
13391
BitField("reserved1", 0, 4),
13492
BitField("version", 2, 4),
135-
ShortField("messageLength", 0),
93+
ShortField("messageLength", None),
13694
ByteField("domainNumber", 0),
13795
ByteField("reserved2", 0),
13896
FlagsField("flags", 0, 16, _flags),
@@ -142,111 +100,61 @@ class PTPHeader(Packet):
142100
ShortField("portNumber", 0),
143101
ShortField("sequenceId", 0),
144102
ByteEnumField("controlField", 0, _control_field),
145-
ByteField("logMessageInterval", 0)
146-
]
103+
ByteField("logMessageInterval", 0),
104+
ConditionalField(BitField("originTimestamp_seconds", 0, 48),
105+
lambda pkt: pkt.messageType in [0x0, 0x1, 0x2, 0xB]),
106+
ConditionalField(IntField("originTimestamp_nanoseconds", 0),
107+
lambda pkt: pkt.messageType in [0x0, 0x1, 0x2, 0xB]),
108+
ConditionalField(BitField("preciseOriginTimestamp_seconds", 0, 48),
109+
lambda pkt: pkt.messageType == 0x8),
110+
ConditionalField(IntField("preciseOriginTimestamp_nanoseconds", 0),
111+
lambda pkt: pkt.messageType == 0x8),
112+
ConditionalField(BitField("requestReceiptTimestamp_seconds", 0, 48),
113+
lambda pkt: pkt.messageType == 0x3),
114+
ConditionalField(IntField("requestReceiptTimestamp_nanoseconds", 0),
115+
lambda pkt: pkt.messageType == 0x3),
116+
ConditionalField(BitField("receiveTimestamp_seconds", 0, 48),
117+
lambda pkt: pkt.messageType == 0x9),
118+
ConditionalField(IntField("receiveTimestamp_nanoseconds", 0),
119+
lambda pkt: pkt.messageType == 0x9),
120+
ConditionalField(BitField("responseOriginTimestamp_seconds", 0, 48),
121+
lambda pkt: pkt.messageType == 0xA),
122+
ConditionalField(IntField("responseOriginTimestamp_nanoseconds", 0),
123+
lambda pkt: pkt.messageType == 0xA),
124+
ConditionalField(ShortField("currentUtcOffset", 0),
125+
lambda pkt: pkt.messageType == 0xB),
126+
ConditionalField(ByteField("reserved4", 0),
127+
lambda pkt: pkt.messageType == 0xB),
128+
ConditionalField(ByteField("grandmasterPriority1", 0),
129+
lambda pkt: pkt.messageType == 0xB),
130+
ConditionalField(ByteField("grandmasterClockClass", 0),
131+
lambda pkt: pkt.messageType == 0xB),
132+
ConditionalField(XByteField("grandmasterClockAccuracy", 0),
133+
lambda pkt: pkt.messageType == 0xB),
134+
ConditionalField(ShortField("grandmasterClockVariance", 0),
135+
lambda pkt: pkt.messageType == 0xB),
136+
ConditionalField(ByteField("grandmasterPriority2", 0),
137+
lambda pkt: pkt.messageType == 0xB),
138+
ConditionalField(XLongField("grandmasterIdentity", 0),
139+
lambda pkt: pkt.messageType == 0xB),
140+
ConditionalField(ShortField("stepsRemoved", 0),
141+
lambda pkt: pkt.messageType == 0xB),
142+
ConditionalField(XByteField("timeSource", 0),
143+
lambda pkt: pkt.messageType == 0xB)
147144

148-
def guess_payload_class(self, payload): # type: (bytes) -> Type[Packet]
149-
"""
150-
Guess payload class based on messageType
151-
"""
152-
153-
if self.messageType == 0x0:
154-
return Sync
155-
elif self.messageType == 0x1:
156-
return DelayReq
157-
elif self.messageType == 0x2:
158-
return PDelayReq
159-
elif self.messageType == 0x3:
160-
return PDelayResp
161-
elif self.messageType == 0x8:
162-
return FollowUp
163-
elif self.messageType == 0x9:
164-
return DelayResp
165-
elif self.messageType == 0xA:
166-
return PDelayRespFollow
167-
elif self.messageType == 0xB:
168-
return Announce
169-
elif self.messageType == 0xC:
170-
return Signaling
171-
elif self.messageType == 0xD:
172-
return Management
173-
174-
return Packet.guess_payload_class(self, payload)
145+
]
175146

176147
def post_build(self, pkt, pay): # type: (bytes, bytes) -> bytes
177148
"""
178149
Update the messageLength field after building the packet
179150
"""
180-
pass
181-
182-
183-
class Sync(Packet):
184-
"""
185-
Handle the Sync message type in PTP
186-
"""
187-
name = "Sync"
188-
fields_desc = [
189-
PacketField("originTimestamp", 0, OriginTimestamp)
190-
]
191-
192-
193-
class DelayReq(Packet):
194-
"""
195-
Handle the DelayReq message type in PTP
196-
"""
151+
if self.messageLength is None:
152+
pkt = pkt[:2] + struct.pack("!H", len(pkt)) + pkt[4:]
197153

198-
199-
class PDelayReq(Packet):
200-
"""
201-
Handle the PDelayReq message type in PTP
202-
"""
203-
204-
205-
class FollowUp(Packet):
206-
"""
207-
Handle the FollowUp message type in PTP
208-
"""
209-
210-
211-
class PDelayResp(Packet):
212-
"""
213-
Handle the PDelayResp message type in PTP
214-
"""
215-
216-
217-
class DelayResp(Packet):
218-
"""
219-
Handle the DelayResp message type in PTP
220-
"""
221-
222-
223-
class PDelayRespFollow(Packet):
224-
"""
225-
Handle the PDelayRespFollow message type in PTP
226-
"""
227-
228-
229-
class Announce(Packet):
230-
"""
231-
Handle the Announce message type in PTP
232-
"""
233-
234-
235-
class Signaling(Packet):
236-
"""
237-
Handle the Signaling message type in PTP
238-
"""
239-
240-
241-
class Management(Packet):
242-
"""
243-
Handle the Management message type in PTP
244-
"""
154+
return pkt + pay
245155

246156

247-
##############################################################################
248157
# Layer bindings
249-
##############################################################################
250158

251-
bind_layers(UDP, PTPHeader, sport=319, dport=319)
252-
bind_layers(UDP, PTPHeader, sport=320, dport=320)
159+
bind_layers(UDP, PTP, sport=319, dport=319)
160+
bind_layers(UDP, PTP, sport=320, dport=320)

0 commit comments

Comments
 (0)