1 /*
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
12 *
13 * Original code by Partha S. Ghosh (psglinux dot gmail dot com)
14 */
15
16 /* \summary: Precision Time Protocol (PTP) printer */
17
18 /* specification: https://standards.ieee.org/findstds/standard/1588-2008.html*/
19
20 #include <config.h>
21
22 #include "netdissect-stdinc.h"
23 #include "netdissect.h"
24 #include "extract.h"
25
26 /*
27 * PTP header
28 * 0 1 2 3
29 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
30 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31 * | R | |msgtype| version | Msg Len |
32 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
33 * | domain No | rsvd1 | flag Field |
34 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
35 * | Correction NS |
36 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
37 * | | Correction Sub NS |
38 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
39 * | Reserved2 |
40 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
41 * | Clock Identity |
42 * | |
43 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 * | Port Identity | Sequence ID |
45 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 * | control | log msg int |
47 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
49 * 0 1 2 3
50 *
51 * Announce Message (msg type=0xB)
52 * 0 1 2 3
53 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
54 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
55 * | |
56 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
57 * | Seconds |
58 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
59 * | Nano Seconds |
60 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
61 * | Origin Cur UTC Offset | Reserved | GM Prio 1 |
62 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
63 * |GM Clock Class | GM Clock Accu | GM Clock Variance |
64 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
65 * | GM Prio 2 | |
66 * +-+-+-+-+-+-+-+-+ +
67 * | GM Clock Identity |
68 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
69 * | | Steps Removed | Time Source |
70 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
71 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
72 * 0 1 2 3
73 *
74 * Sync Message (msg type=0x0)
75 * 0 1 2 3
76 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
77 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78 * | |
79 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
80 * | Seconds |
81 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 * | Nano Seconds |
83 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 *
85 * Delay Request Message (msg type=0x1)
86 * 0 1 2 3
87 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
88 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * | |
90 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
91 * | Origin Time Stamp Seconds |
92 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 * | Nano Seconds |
94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 *
96 * Followup Message (msg type=0x8)
97 * 0 1 2 3
98 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
99 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
100 * | |
101 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
102 * | Precise Origin Time Stamp Seconds |
103 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
104 * | Nano Seconds |
105 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 *
107 * Delay Resp Message (msg type=0x9)
108 * 0 1 2 3
109 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
110 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111 * | |
112 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
113 * | Seconds |
114 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
115 * | Nano Seconds |
116 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117 * | Port Identity |
118 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119 *
120 * PDelay Request Message (msg type=0x2)
121 * 0 1 2 3
122 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
123 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
124 * | |
125 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
126 * | Origin Time Stamp Seconds |
127 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
128 * | Origin Time Stamp Nano Seconds |
129 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
130 * | Port Identity |
131 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
132 *
133 * PDelay Response Message (msg type=0x3)
134 * 0 1 2 3
135 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
136 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
137 * | |
138 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
139 * | Request receipt Time Stamp Seconds |
140 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
141 * | Nano Seconds |
142 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143 * | Requesting Port Identity |
144 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
145 *
146 * PDelay Resp Follow up Message (msg type=0xA)
147 * 0 1 2 3
148 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
149 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
150 * | |
151 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
152 * | Response Origin Time Stamp Seconds |
153 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
154 * | Nano Seconds |
155 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
156 * | Requesting Port Identity |
157 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
158 *
159 * Signaling Message (msg type=0xC)
160 * 0 1 2 3
161 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
162 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
163 * | Requesting Port Identity |
164 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
165 *
166 * Management Message (msg type=0xD)
167 * 0 1 2 3
168 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
169 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
170 * | Requesting Port Identity |
171 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
172 * |Start Bndry Hps| Boundary Hops | flags | Reserved |
173 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
174 *
175 */
176
177 /* Values from IEEE1588-2008: 13.3.2.2 messageType (Enumeration4) */
178 #define M_SYNC 0x0
179 #define M_DELAY_REQ 0x1
180 #define M_PDELAY_REQ 0x2
181 #define M_PDELAY_RESP 0x3
182 #define M_FOLLOW_UP 0x8
183 #define M_DELAY_RESP 0x9
184 #define M_PDELAY_RESP_FOLLOW_UP 0xA
185 #define M_ANNOUNCE 0xB
186 #define M_SIGNALING 0xC
187 #define M_MANAGEMENT 0xD
188
189 static const struct tok ptp_msg_type[] = {
190 { M_SYNC, "sync msg"},
191 { M_DELAY_REQ, "delay req msg"},
192 { M_PDELAY_REQ, "peer delay req msg"},
193 { M_PDELAY_RESP, "peer delay resp msg"},
194 { M_FOLLOW_UP, "follow up msg"},
195 { M_DELAY_RESP, "delay resp msg"},
196 { M_PDELAY_RESP_FOLLOW_UP, "pdelay resp fup msg"},
197 { M_ANNOUNCE, "announce msg"},
198 { M_SIGNALING, "signaling msg"},
199 { M_MANAGEMENT, "management msg"},
200 { 0, NULL}
201 };
202
203 /* Values from IEEE1588-2008: 13.3.2.10 controlField (UInteger8) */
204 /*
205 * The use of this field by the receiver is deprecated.
206 * NOTE-This field is provided for compatibility with hardware designed
207 * to conform to version 1 of this standard.
208 */
209 #define C_SYNC 0x0
210 #define C_DELAY_REQ 0x1
211 #define C_FOLLOW_UP 0x2
212 #define C_DELAY_RESP 0x3
213 #define C_MANAGEMENT 0x4
214 #define C_OTHER 0x5
215
216 static const struct tok ptp_control_field[] = {
217 { C_SYNC, "Sync"},
218 { C_DELAY_REQ, "Delay_Req"},
219 { C_FOLLOW_UP, "Follow_Up"},
220 { C_DELAY_RESP, "Delay_Resp"},
221 { C_MANAGEMENT, "Management"},
222 { C_OTHER, "Other"},
223 { 0, NULL}
224 };
225
226 #define PTP_TRUE 1
227 #define PTP_FALSE !PTP_TRUE
228
229 #define PTP_HDR_LEN 0x22
230
231 /* mask based on the first byte */
232 #define PTP_MAJOR_VERS_MASK 0x0F
233 #define PTP_MINOR_VERS_MASK 0xF0
234 #define PTP_MAJOR_SDO_ID_MASK 0xF0
235 #define PTP_MSG_TYPE_MASK 0x0F
236
237 /*mask based 2byte */
238 #define PTP_DOMAIN_MASK 0xFF00
239 #define PTP_RSVD1_MASK 0xFF
240 #define PTP_CONTROL_MASK 0xFF
241 #define PTP_LOGMSG_MASK 0xFF
242
243 /* mask based on the flags 2 bytes */
244
245 #define PTP_L161_MASK 0x1
246 #define PTP_L1_59_MASK 0x2
247 #define PTP_UTC_REASONABLE_MASK 0x4
248 #define PTP_TIMESCALE_MASK 0x8
249 #define PTP_TIME_TRACABLE_MASK 0x10
250 #define PTP_FREQUENCY_TRACABLE_MASK 0x20
251 #define PTP_ALTERNATE_MASTER_MASK 0x100
252 #define PTP_TWO_STEP_MASK 0x200
253 #define PTP_UNICAST_MASK 0x400
254 #define PTP_PROFILE_SPEC_1_MASK 0x1000
255 #define PTP_PROFILE_SPEC_2_MASK 0x2000
256 #define PTP_SECURITY_MASK 0x4000
257 #define PTP_FLAGS_UNKNOWN_MASK 0x18C0
258
259 static const struct tok ptp_flag_values[] = {
260 { PTP_L161_MASK, "l1 61"},
261 { PTP_L1_59_MASK, "l1 59"},
262 { PTP_UTC_REASONABLE_MASK, "utc reasonable"},
263 { PTP_TIMESCALE_MASK, "timescale"},
264 { PTP_TIME_TRACABLE_MASK, "time tracable"},
265 { PTP_FREQUENCY_TRACABLE_MASK, "frequency tracable"},
266 { PTP_ALTERNATE_MASTER_MASK, "alternate master"},
267 { PTP_TWO_STEP_MASK, "two step"},
268 { PTP_UNICAST_MASK, "unicast"},
269 { PTP_PROFILE_SPEC_1_MASK, "profile specific 1"},
270 { PTP_PROFILE_SPEC_2_MASK, "profile specific 2"},
271 { PTP_SECURITY_MASK, "security mask"},
272 { PTP_FLAGS_UNKNOWN_MASK, "unknown"},
273 {0, NULL}
274 };
275
276 static const char *p_porigin_ts = "preciseOriginTimeStamp";
277 static const char *p_origin_ts = "originTimeStamp";
278 static const char *p_recv_ts = "receiveTimeStamp";
279
280 #define PTP_VER_1 0x1
281 #define PTP_VER_2 0x2
282
283 #define PTP_UCHAR_LEN sizeof(uint8_t)
284 #define PTP_UINT16_LEN sizeof(uint16_t)
285 #define PTP_UINT32_LEN sizeof(uint32_t)
286 #define PTP_6BYTES_LEN sizeof(uint32_t)+sizeof(uint16_t)
287 #define PTP_UINT64_LEN sizeof(uint64_t)
288
289 static void ptp_print_1(netdissect_options *ndo);
290 static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int len);
291
292 static void ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype);
293 static void ptp_print_timestamp_identity(netdissect_options *ndo, const u_char *bp, u_int *len, const char *ttype);
294 static void ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
295 static void ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len);
296 static void ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
297
298 static void
print_field(netdissect_options * ndo,const char * st,uint32_t flen,const u_char * bp,u_int * len,uint8_t hex)299 print_field(netdissect_options *ndo, const char *st, uint32_t flen,
300 const u_char *bp, u_int *len, uint8_t hex)
301 {
302 uint8_t u8_val;
303 uint16_t u16_val;
304 uint32_t u32_val;
305 uint64_t u64_val;
306
307 switch(flen) {
308 case PTP_UCHAR_LEN:
309 u8_val = GET_U_1(bp);
310 ND_PRINT(", %s", st);
311 if (hex)
312 ND_PRINT(" 0x%x", u8_val);
313 else
314 ND_PRINT(" %u", u8_val);
315 *len -= 1; bp += 1;
316 break;
317 case PTP_UINT16_LEN:
318 u16_val = GET_BE_U_2(bp);
319 ND_PRINT(", %s", st);
320 if (hex)
321 ND_PRINT(" 0x%x", u16_val);
322 else
323 ND_PRINT(" %u", u16_val);
324 *len -= 2; bp += 2;
325 break;
326 case PTP_UINT32_LEN:
327 u32_val = GET_BE_U_4(bp);
328 ND_PRINT(", %s", st);
329 if (hex)
330 ND_PRINT(" 0x%x", u32_val);
331 else
332 ND_PRINT(" %u", u32_val);
333 *len -= 4; bp += 4;
334 break;
335 case PTP_UINT64_LEN:
336 u64_val = GET_BE_U_8(bp);
337 ND_PRINT(", %s", st);
338 if (hex)
339 ND_PRINT(" 0x%"PRIx64, u64_val);
340 else
341 ND_PRINT(" 0x%"PRIu64, u64_val);
342 *len -= 8; bp += 8;
343 break;
344 default:
345 break;
346 }
347 }
348
349 static void
ptp_print_1(netdissect_options * ndo)350 ptp_print_1(netdissect_options *ndo)
351 {
352 ND_PRINT(" (not implemented)");
353 }
354
355 static void
ptp_print_2(netdissect_options * ndo,const u_char * bp,u_int length)356 ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
357 {
358 u_int len = length;
359 uint16_t msg_len, flags, port_id, seq_id;
360 uint8_t foct, domain_no, msg_type, major_sdo_id, rsvd1, lm_int, control;
361 uint64_t ns_corr;
362 uint16_t sns_corr;
363 uint32_t rsvd2;
364 uint64_t clk_id;
365
366 foct = GET_U_1(bp);
367 major_sdo_id = (foct & PTP_MAJOR_SDO_ID_MASK) >> 4;
368 ND_PRINT(", majorSdoId : 0x%x", major_sdo_id);
369 msg_type = foct & PTP_MSG_TYPE_MASK;
370 ND_PRINT(", msg type : %s", tok2str(ptp_msg_type, "Reserved", msg_type));
371
372 /* msg length */
373 len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length : %u", msg_len);
374
375 /* domain */
376 len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain : %u", domain_no);
377
378 /* rsvd 1*/
379 rsvd1 = GET_BE_U_2(bp) & PTP_RSVD1_MASK;
380 ND_PRINT(", reserved1 : %u", rsvd1);
381
382 /* flags */
383 len -= 2; bp += 2; flags = GET_BE_U_2(bp); ND_PRINT(", Flags [%s]", bittok2str(ptp_flag_values, "none", flags));
384
385 /* correction NS (48 bits) */
386 len -= 2; bp += 2; ns_corr = GET_BE_U_6(bp); ND_PRINT(", NS correction : %"PRIu64, ns_corr);
387
388 /* correction sub NS (16 bits) */
389 len -= 6; bp += 6; sns_corr = GET_BE_U_2(bp); ND_PRINT(", sub NS correction : %u", sns_corr);
390
391 /* Reserved 2 */
392 len -= 2; bp += 2; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2 : %u", rsvd2);
393
394 /* clock identity */
395 len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity : 0x%"PRIx64, clk_id);
396
397 /* port identity */
398 len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id : %u", port_id);
399
400 /* sequence ID */
401 len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id : %u", seq_id);
402
403 /* control */
404 len -= 2; bp += 2; control = GET_U_1(bp) ;
405 ND_PRINT(", control : %u (%s)", control, tok2str(ptp_control_field, "Reserved", control));
406
407 /* log message interval */
408 lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval : %u", lm_int); len -= 2; bp += 2;
409
410 switch(msg_type) {
411 case M_SYNC:
412 ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
413 break;
414 case M_DELAY_REQ:
415 ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
416 break;
417 case M_PDELAY_REQ:
418 ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
419 break;
420 case M_PDELAY_RESP:
421 ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
422 break;
423 case M_FOLLOW_UP:
424 ptp_print_timestamp(ndo, bp, &len, p_porigin_ts);
425 break;
426 case M_DELAY_RESP:
427 ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
428 break;
429 case M_PDELAY_RESP_FOLLOW_UP:
430 ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
431 break;
432 case M_ANNOUNCE:
433 ptp_print_announce_msg(ndo, bp, &len);
434 break;
435 case M_SIGNALING:
436 ptp_print_port_id(ndo, bp, &len);
437 break;
438 case M_MANAGEMENT:
439 ptp_print_mgmt_msg(ndo, bp, &len);
440 break;
441 default:
442 break;
443 }
444 }
445 /*
446 * PTP general message
447 */
448 void
ptp_print(netdissect_options * ndo,const u_char * bp,u_int length)449 ptp_print(netdissect_options *ndo, const u_char *bp, u_int length)
450 {
451 u_int major_vers;
452 u_int minor_vers;
453
454 /* In 1588-2019, a minorVersionPTP field has been created in the common PTP
455 * message header, from a previously reserved field. Implementations
456 * compatible to the 2019 edition shall indicate a versionPTP field value
457 * of 2 and minorVersionPTP field value of 1, indicating that this is PTP
458 * version 2.1.
459 */
460 ndo->ndo_protocol = "ptp";
461 ND_ICHECK_U(length, <, PTP_HDR_LEN);
462 major_vers = GET_BE_U_2(bp) & PTP_MAJOR_VERS_MASK;
463 minor_vers = (GET_BE_U_2(bp) & PTP_MINOR_VERS_MASK) >> 4;
464 if (minor_vers)
465 ND_PRINT("PTPv%u.%u", major_vers, minor_vers);
466 else
467 ND_PRINT("PTPv%u", major_vers);
468
469 switch(major_vers) {
470 case PTP_VER_1:
471 ptp_print_1(ndo);
472 break;
473 case PTP_VER_2:
474 ptp_print_2(ndo, bp, length);
475 break;
476 default:
477 //ND_PRINT("ERROR: unknown-version\n");
478 break;
479 }
480 return;
481
482 invalid:
483 nd_print_invalid(ndo);
484 }
485
486 static void
ptp_print_timestamp(netdissect_options * ndo,const u_char * bp,u_int * len,const char * stype)487 ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype)
488 {
489 uint64_t secs;
490 uint32_t nsecs;
491
492 ND_PRINT(", %s :", stype);
493 /* sec time stamp 6 bytes */
494 secs = GET_BE_U_6(bp);
495 ND_PRINT(" %"PRIu64" seconds,", secs);
496 *len -= 6;
497 bp += 6;
498
499 /* NS time stamp 4 bytes */
500 nsecs = GET_BE_U_4(bp);
501 ND_PRINT(" %u nanoseconds", nsecs);
502 *len -= 4;
503 bp += 4;
504 }
505 static void
ptp_print_timestamp_identity(netdissect_options * ndo,const u_char * bp,u_int * len,const char * ttype)506 ptp_print_timestamp_identity(netdissect_options *ndo,
507 const u_char *bp, u_int *len, const char *ttype)
508 {
509 uint64_t secs;
510 uint32_t nsecs;
511 uint16_t port_id;
512 uint64_t port_identity;
513
514 ND_PRINT(", %s :", ttype);
515 /* sec time stamp 6 bytes */
516 secs = GET_BE_U_6(bp);
517 ND_PRINT(" %"PRIu64" seconds,", secs);
518 *len -= 6;
519 bp += 6;
520
521 /* NS time stamp 4 bytes */
522 nsecs = GET_BE_U_4(bp);
523 ND_PRINT(" %u nanoseconds", nsecs);
524 *len -= 4;
525 bp += 4;
526
527 /* port identity*/
528 port_identity = GET_BE_U_8(bp);
529 ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
530 *len -= 8;
531 bp += 8;
532
533 /* port id */
534 port_id = GET_BE_U_2(bp);
535 ND_PRINT(", port id : %u", port_id);
536 *len -= 2;
537 bp += 2;
538 }
539 static void
ptp_print_announce_msg(netdissect_options * ndo,const u_char * bp,u_int * len)540 ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
541 {
542 uint8_t rsvd, gm_prio_1, gm_prio_2, gm_clk_cls, gm_clk_acc, time_src;
543 uint16_t origin_cur_utc, gm_clk_var, steps_removed;
544 uint64_t gm_clock_id;
545 uint64_t secs;
546 uint32_t nsecs;
547
548 ND_PRINT(", %s :", p_origin_ts);
549 /* sec time stamp 6 bytes */
550 secs = GET_BE_U_6(bp);
551 ND_PRINT(" %"PRIu64" seconds", secs);
552 *len -= 6;
553 bp += 6;
554
555 /* NS time stamp 4 bytes */
556 nsecs = GET_BE_U_4(bp);
557 ND_PRINT(" %u nanoseconds", nsecs);
558 *len -= 4;
559 bp += 4;
560
561 /* origin cur utc */
562 origin_cur_utc = GET_BE_U_2(bp);
563 ND_PRINT(", origin cur utc :%u", origin_cur_utc);
564 *len -= 2;
565 bp += 2;
566
567 /* rsvd */
568 rsvd = GET_U_1(bp);
569 ND_PRINT(", rsvd : %u", rsvd);
570 *len -= 1;
571 bp += 1;
572
573 /* gm prio */
574 gm_prio_1 = GET_U_1(bp);
575 ND_PRINT(", gm priority_1 : %u", gm_prio_1);
576 *len -= 1;
577 bp += 1;
578
579 /* GM clock class */
580 gm_clk_cls = GET_U_1(bp);
581 ND_PRINT(", gm clock class : %u", gm_clk_cls);
582 *len -= 1;
583 bp += 1;
584 /* GM clock accuracy */
585 gm_clk_acc = GET_U_1(bp);
586 ND_PRINT(", gm clock accuracy : %u", gm_clk_acc);
587 *len -= 1;
588 bp += 1;
589 /* GM clock variance */
590 gm_clk_var = GET_BE_U_2(bp);
591 ND_PRINT(", gm clock variance : %u", gm_clk_var);
592 *len -= 2;
593 bp += 2;
594 /* GM Prio 2 */
595 gm_prio_2 = GET_U_1(bp);
596 ND_PRINT(", gm priority_2 : %u", gm_prio_2);
597 *len -= 1;
598 bp += 1;
599
600 /* GM Clock Identity */
601 gm_clock_id = GET_BE_U_8(bp);
602 ND_PRINT(", gm clock id : 0x%"PRIx64, gm_clock_id);
603 *len -= 8;
604 bp += 8;
605 /* steps removed */
606 steps_removed = GET_BE_U_2(bp);
607 ND_PRINT(", steps removed : %u", steps_removed);
608 *len -= 2;
609 bp += 2;
610 /* Time source */
611 time_src = GET_U_1(bp);
612 ND_PRINT(", time source : 0x%x", time_src);
613 *len -= 1;
614 bp += 1;
615
616 }
617 static void
ptp_print_port_id(netdissect_options * ndo,const u_char * bp,u_int * len)618 ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
619 {
620 uint16_t port_id;
621 uint64_t port_identity;
622
623 /* port identity*/
624 port_identity = GET_BE_U_8(bp);
625 ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
626 *len -= 8;
627 bp += 8;
628
629 /* port id */
630 port_id = GET_BE_U_2(bp);
631 ND_PRINT(", port id : %u", port_id);
632 *len -= 2;
633 bp += 2;
634
635 }
636
637 static void
ptp_print_mgmt_msg(netdissect_options * ndo,const u_char * bp,u_int * len)638 ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
639 {
640 ptp_print_port_id(ndo, bp, len);
641 print_field(ndo, ", start boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
642 print_field(ndo, ", boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
643 print_field(ndo, ", flags ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
644 print_field(ndo, ", reserved ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
645 }
646