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