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