Skip to content

Commit 7ead379

Browse files
committed
Add initial PTP support with header and message types
- Implement PTP header structure based on IEEE 1588-2008 - Implement Sync message type class
1 parent 92925da commit 7ead379

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed

scapy/layers/ptp_v2.py

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
# This file is part of Scapy
3+
# See https://scapy.net/ for more information
4+
# Copyright (C) Philippe Biondi <phil@secdev.org>
5+
# Copyright (C) Satveer Brar
6+
7+
"""
8+
PTP (Precision Time Protocol).
9+
References : IEEE 1588-2008
10+
"""
11+
12+
from scapy.packet import Packet, bind_layers
13+
from scapy.fields import (
14+
BitEnumField,
15+
BitField,
16+
ByteField,
17+
IntField,
18+
LongField,
19+
ShortField,
20+
ByteEnumField,
21+
FlagsField,
22+
PacketField,
23+
XLongField,
24+
)
25+
from scapy.layers.inet import UDP
26+
27+
28+
#############################################################################
29+
# PTPv2
30+
#############################################################################
31+
32+
# IEEE 1588-2008 / Section 13.3.2.2
33+
34+
_message_type = {
35+
0x0: "Sync",
36+
0x1: "Delay_Req",
37+
0x2: "Pdelay_Req",
38+
0x3: "Pdelay_Resp",
39+
0x4: "Reserved",
40+
0x5: "Reserved",
41+
0x6: "Reserved",
42+
0x7: "Reserved",
43+
0x8: "Follow_Up",
44+
0x9: "Delay_Resp",
45+
0xA: "Pdelay_Resp_Follow",
46+
0xB: "Announce",
47+
0xC: "Signaling",
48+
0xD: "Management",
49+
0xE: "Reserved",
50+
0xF: "Reserved"
51+
}
52+
53+
_control_field = {
54+
0x00: "Sync",
55+
0x01: "Delay_Req",
56+
0x02: "Follow_Up",
57+
0x03: "Delay_Resp",
58+
0x04: "Management",
59+
0x05: "All others",
60+
}
61+
62+
_flags = {
63+
0x0001: "alternateMasterFlag",
64+
0x0002: "twoStepFlag",
65+
0x0004: "unicastFlag",
66+
0x0010: "ptpProfileSpecific1",
67+
0x0020: "ptpProfileSpecific2",
68+
0x0040: "reserved",
69+
0x0100: "leap61",
70+
0x0200: "leap59",
71+
0x0400: "currentUtcOffsetValid",
72+
0x0800: "ptpTimescale",
73+
0x1000: "timeTraceable",
74+
0x2000: "frequencyTraceable"
75+
}
76+
77+
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):
87+
"""
88+
PTP Header based on IEEE 1588-2008 / Section 13.3.
89+
"""
90+
name = "PTPHeader"
91+
match_subclass = True
92+
fields_desc = [
93+
BitField("transportSpecific", 0, 4),
94+
BitEnumField("messageType", 0x0, 4, _message_type),
95+
BitField("reserved1", 0, 4),
96+
BitField("version", 2, 4),
97+
ShortField("messageLength", 0),
98+
ByteField("domainNumber", 0),
99+
ByteField("reserved2", 0),
100+
FlagsField("flags", 0, 16, _flags),
101+
LongField("correctionField", 0),
102+
IntField("reserved3", 0),
103+
XLongField("clockIdentity", 0),
104+
ShortField("portNumber", 0),
105+
ShortField("sequenceId", 0),
106+
ByteEnumField("controlField", 0, _control_field),
107+
ByteField("logMessageInterval", 0)
108+
]
109+
110+
def guess_payload_class(self, payload): # type: (bytes) -> Type[Packet]
111+
"""
112+
Guess payload class based on messageType
113+
"""
114+
115+
if self.messageType == 0x0:
116+
return Sync
117+
elif self.messageType == 0x1:
118+
return DelayReq
119+
elif self.messageType == 0x2:
120+
return PDelayReq
121+
elif self.messageType == 0x3:
122+
return PDelayResp
123+
elif self.messageType == 0x8:
124+
return FollowUp
125+
elif self.messageType == 0x9:
126+
return DelayResp
127+
elif self.messageType == 0xA:
128+
return PDelayRespFollow
129+
elif self.messageType == 0xB:
130+
return Announce
131+
elif self.messageType == 0xC:
132+
return Signaling
133+
elif self.messageType == 0xD:
134+
return Management
135+
136+
return Packet.guess_payload_class(self, payload)
137+
138+
def post_build(self, pkt, pay): # type: (bytes, bytes) -> bytes
139+
"""
140+
Update the messageLength field after building the packet
141+
"""
142+
pass
143+
144+
145+
class Sync(Packet):
146+
"""
147+
Handle the Sync message type in PTP
148+
"""
149+
name = "Sync"
150+
fields_desc = [
151+
PacketField("originTimestamp", 0, OriginTimestamp)
152+
]
153+
154+
155+
class DelayReq(Packet):
156+
"""
157+
Handle the DelayReq message type in PTP
158+
"""
159+
160+
161+
class PDelayReq(Packet):
162+
"""
163+
Handle the PDelayReq message type in PTP
164+
"""
165+
166+
167+
class FollowUp(Packet):
168+
"""
169+
Handle the FollowUp message type in PTP
170+
"""
171+
172+
173+
class PDelayResp(Packet):
174+
"""
175+
Handle the PDelayResp message type in PTP
176+
"""
177+
178+
179+
class DelayResp(Packet):
180+
"""
181+
Handle the DelayResp message type in PTP
182+
"""
183+
184+
185+
class PDelayRespFollow(Packet):
186+
"""
187+
Handle the PDelayRespFollow message type in PTP
188+
"""
189+
190+
191+
class Announce(Packet):
192+
"""
193+
Handle the Announce message type in PTP
194+
"""
195+
196+
197+
class Signaling(Packet):
198+
"""
199+
Handle the Signaling message type in PTP
200+
"""
201+
202+
203+
class Management(Packet):
204+
"""
205+
Handle the Management message type in PTP
206+
"""
207+
208+
209+
##############################################################################
210+
# Layer bindings
211+
##############################################################################
212+
213+
bind_layers(UDP, PTPHeader, sport=319, dport=319)
214+
bind_layers(UDP, PTPHeader, sport=320, dport=320)

0 commit comments

Comments
 (0)