]> The Tcpdump Group git mirrors - tcpdump/blob - print-ptp.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[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 #include <config.h>
21
22 #include "netdissect-stdinc.h"
23 #include "netdissect.h"
24 #include "extract.h"
25 #include "timeval-operations.h"
26
27 /*
28 * PTP header
29 * 0 1 2 3
30 * 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
31 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
32 * | R | |msgtype| version | Msg Len |
33 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
34 * | domain No | rsvd1 | flag Field |
35 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36 * | Correction NS |
37 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38 * | | Correction Sub NS |
39 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40 * | Reserved2 |
41 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 * | Clock Identity |
43 * | |
44 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
45 * | Port Identity | Sequence ID |
46 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
47 * | control | log msg int |
48 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
49 * 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
50 * 0 1 2 3
51 *
52 * Announce Message (msg type=0xB)
53 * 0 1 2 3
54 * 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
55 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 * | |
57 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
58 * | Seconds |
59 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 * | Nano Seconds |
61 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62 * | Origin Cur UTC Offset | Reserved | GM Prio 1 |
63 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64 * |GM Clock Class | GM Clock Accu | GM Clock Variance |
65 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66 * | GM Prio 2 | |
67 * +-+-+-+-+-+-+-+-+ +
68 * | GM Clock Identity |
69 * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70 * | | Steps Removed | Time Source |
71 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 * 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
73 * 0 1 2 3
74 *
75 * Sync Message (msg type=0x0)
76 * 0 1 2 3
77 * 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
78 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
79 * | |
80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
81 * | Seconds |
82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 * | Nano Seconds |
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 *
86 * Delay Request Message (msg type=0x1)
87 * 0 1 2 3
88 * 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
89 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90 * | |
91 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
92 * | Origin Time Stamp Seconds |
93 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
94 * | Nano Seconds |
95 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96 *
97 * Followup Message (msg type=0x8)
98 * 0 1 2 3
99 * 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
100 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 * | |
102 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
103 * | Precise Origin Time Stamp Seconds |
104 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105 * | Nano Seconds |
106 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 *
108 * Delay Resp Message (msg type=0x9)
109 * 0 1 2 3
110 * 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
111 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
112 * | |
113 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
114 * | Seconds |
115 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116 * | Nano Seconds |
117 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118 * | Port Identity |
119 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
120 *
121 * PDelay Request Message (msg type=0x2)
122 * 0 1 2 3
123 * 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
124 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125 * | |
126 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
127 * | Origin Time Stamp Seconds |
128 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129 * | Origin Time Stamp Nano Seconds |
130 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131 * | Port Identity |
132 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133 *
134 * PDelay Response Message (msg type=0x3)
135 * 0 1 2 3
136 * 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
137 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 * | |
139 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
140 * | Request receipt Time Stamp Seconds |
141 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142 * | Nano Seconds |
143 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
144 * | Requesting Port Identity |
145 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146 *
147 * PDelay Resp Follow up Message (msg type=0xA)
148 * 0 1 2 3
149 * 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
150 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
151 * | |
152 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +
153 * | Response Origin Time Stamp Seconds |
154 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
155 * | Nano Seconds |
156 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
157 * | Requesting Port Identity |
158 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
159 *
160 * Signaling Message (msg type=0xC)
161 * 0 1 2 3
162 * 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
163 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
164 * | Requesting Port Identity |
165 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
166 *
167 * Management Message (msg type=0xD)
168 * 0 1 2 3
169 * 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
170 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
171 * | Requesting Port Identity |
172 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
173 * |Start Bndry Hps| Boundary Hops | flags | Reserved |
174 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175 *
176 */
177
178 /* Values from IEEE1588-2008: 13.3.2.2 messageType (Enumeration4) */
179 #define M_SYNC 0x0
180 #define M_DELAY_REQ 0x1
181 #define M_PDELAY_REQ 0x2
182 #define M_PDELAY_RESP 0x3
183 #define M_FOLLOW_UP 0x8
184 #define M_DELAY_RESP 0x9
185 #define M_PDELAY_RESP_FOLLOW_UP 0xA
186 #define M_ANNOUNCE 0xB
187 #define M_SIGNALING 0xC
188 #define M_MANAGEMENT 0xD
189
190 static const struct tok ptp_msg_type[] = {
191 { M_SYNC, "sync msg"},
192 { M_DELAY_REQ, "delay req msg"},
193 { M_PDELAY_REQ, "peer delay req msg"},
194 { M_PDELAY_RESP, "peer delay resp msg"},
195 { M_FOLLOW_UP, "follow up msg"},
196 { M_DELAY_RESP, "delay resp msg"},
197 { M_PDELAY_RESP_FOLLOW_UP, "pdelay resp fup msg"},
198 { M_ANNOUNCE, "announce msg"},
199 { M_SIGNALING, "signaling msg"},
200 { M_MANAGEMENT, "management msg"},
201 { 0, NULL}
202 };
203
204 /* Values from IEEE1588-2008: 13.3.2.10 controlField (UInteger8) */
205 /*
206 * The use of this field by the receiver is deprecated.
207 * NOTE-This field is provided for compatibility with hardware designed
208 * to conform to version 1 of this standard.
209 */
210 #define C_SYNC 0x0
211 #define C_DELAY_REQ 0x1
212 #define C_FOLLOW_UP 0x2
213 #define C_DELAY_RESP 0x3
214 #define C_MANAGEMENT 0x4
215 #define C_OTHER 0x5
216
217 static const struct tok ptp_control_field[] = {
218 { C_SYNC, "Sync"},
219 { C_DELAY_REQ, "Delay_Req"},
220 { C_FOLLOW_UP, "Follow_Up"},
221 { C_DELAY_RESP, "Delay_Resp"},
222 { C_MANAGEMENT, "Management"},
223 { C_OTHER, "Other"},
224 { 0, NULL}
225 };
226
227 #define PTP_TRUE 1
228 #define PTP_FALSE !PTP_TRUE
229
230 #define PTP_HDR_LEN 0x22
231 #define PTP_TIMESTAMP_LEN 10U
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 const u_char *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 const u_char *
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 return bp;
351 }
352
353 static void
354 ptp_print_1(netdissect_options *ndo)
355 {
356 ND_PRINT(" (not implemented)");
357 }
358
359 static void
360 ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
361 {
362 u_int len = length;
363 uint16_t msg_len, flags, port_id, seq_id;
364 uint8_t foct, domain_no, msg_type, major_sdo_id, rsvd1, lm_int, control;
365 uint64_t ns_corr;
366 uint16_t sns_corr;
367 uint32_t rsvd2;
368 uint64_t clk_id;
369
370 foct = GET_U_1(bp);
371 major_sdo_id = (foct & PTP_MAJOR_SDO_ID_MASK) >> 4;
372 ND_PRINT(", majorSdoId: 0x%x", major_sdo_id);
373 msg_type = foct & PTP_MSG_TYPE_MASK;
374 ND_PRINT(", msg type: %s", tok2str(ptp_msg_type, "Reserved", msg_type));
375
376 /* msg length */
377 len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length: %u", msg_len);
378
379 /* domain */
380 len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain: %u", domain_no);
381
382 /* rsvd 1*/
383 rsvd1 = GET_BE_U_2(bp) & PTP_RSVD1_MASK;
384 ND_PRINT(", reserved1: %u", rsvd1);
385
386 /* flags */
387 len -= 2; bp += 2; flags = GET_BE_U_2(bp); ND_PRINT(", Flags [%s]", bittok2str(ptp_flag_values, "none", flags));
388
389 /* correction NS (48 bits) */
390 len -= 2; bp += 2; ns_corr = GET_BE_U_6(bp); ND_PRINT(", NS correction: %"PRIu64, ns_corr);
391
392 /* correction sub NS (16 bits) */
393 len -= 6; bp += 6; sns_corr = GET_BE_U_2(bp); ND_PRINT(", sub NS correction: %u", sns_corr);
394
395 /* Reserved 2 */
396 len -= 2; bp += 2; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2: %u", rsvd2);
397
398 /* clock identity */
399 len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity: 0x%"PRIx64, clk_id);
400
401 /* port identity */
402 len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id: %u", port_id);
403
404 /* sequence ID */
405 len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id: %u", seq_id);
406
407 /* control */
408 len -= 2; bp += 2; control = GET_U_1(bp) ;
409 ND_PRINT(", control: %u (%s)", control, tok2str(ptp_control_field, "Reserved", control));
410
411 /* log message interval */
412 lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval: %u", lm_int); len -= 2; bp += 2;
413
414 switch(msg_type) {
415 case M_SYNC:
416 ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
417 break;
418 case M_DELAY_REQ:
419 ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
420 break;
421 case M_PDELAY_REQ:
422 ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
423 break;
424 case M_PDELAY_RESP:
425 ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
426 break;
427 case M_FOLLOW_UP:
428 ptp_print_timestamp(ndo, bp, &len, p_porigin_ts);
429 break;
430 case M_DELAY_RESP:
431 ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
432 break;
433 case M_PDELAY_RESP_FOLLOW_UP:
434 ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
435 break;
436 case M_ANNOUNCE:
437 ptp_print_announce_msg(ndo, bp, &len);
438 break;
439 case M_SIGNALING:
440 ptp_print_port_id(ndo, bp, &len);
441 break;
442 case M_MANAGEMENT:
443 ptp_print_mgmt_msg(ndo, bp, &len);
444 break;
445 default:
446 break;
447 }
448 }
449 /*
450 * PTP general message
451 */
452 void
453 ptp_print(netdissect_options *ndo, const u_char *bp, u_int length)
454 {
455 u_int major_vers;
456 u_int minor_vers;
457
458 /* In 1588-2019, a minorVersionPTP field has been created in the common PTP
459 * message header, from a previously reserved field. Implementations
460 * compatible to the 2019 edition shall indicate a versionPTP field value
461 * of 2 and minorVersionPTP field value of 1, indicating that this is PTP
462 * version 2.1.
463 */
464 ndo->ndo_protocol = "ptp";
465 nd_print_protocol_caps(ndo);
466 ND_ICHECK_U(length, <, PTP_HDR_LEN);
467 major_vers = GET_BE_U_2(bp) & PTP_MAJOR_VERS_MASK;
468 minor_vers = (GET_BE_U_2(bp) & PTP_MINOR_VERS_MASK) >> 4;
469 if (minor_vers)
470 ND_PRINT("v%u.%u", major_vers, minor_vers);
471 else
472 ND_PRINT("v%u", major_vers);
473
474 switch(major_vers) {
475 case PTP_VER_1:
476 ptp_print_1(ndo);
477 break;
478 case PTP_VER_2:
479 ptp_print_2(ndo, bp, length);
480 break;
481 default:
482 ND_PRINT(" (unsupported)");
483 break;
484 }
485 return;
486
487 invalid:
488 nd_print_invalid(ndo);
489 }
490
491 static void
492 ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype)
493 {
494 uint64_t secs;
495 uint32_t nsecs;
496
497 ND_PRINT(", %s:", stype);
498 /* sec time stamp 6 bytes */
499 secs = GET_BE_U_6(bp);
500 ND_PRINT(" %"PRIu64".", secs);
501 *len -= 6;
502 bp += 6;
503
504 /* NS time stamp 4 bytes */
505 nsecs = GET_BE_U_4(bp);
506 ND_PRINT("%09u seconds", nsecs);
507 if (nsecs > ND_NANO_PER_SEC - 1)
508 ND_PRINT(" " ND_INVALID_NANO_SEC_STR);
509 *len -= 4;
510 bp += 4;
511 }
512 static void
513 ptp_print_timestamp_identity(netdissect_options *ndo,
514 const u_char *bp, u_int *len, const char *ttype)
515 {
516 uint16_t port_id;
517 uint64_t port_identity;
518
519 ptp_print_timestamp(ndo, bp, len, ttype);
520 *len -= PTP_TIMESTAMP_LEN;
521 bp += PTP_TIMESTAMP_LEN;
522
523 /* port identity*/
524 port_identity = GET_BE_U_8(bp);
525 ND_PRINT(", port identity: 0x%"PRIx64, port_identity);
526 *len -= 8;
527 bp += 8;
528
529 /* port id */
530 port_id = GET_BE_U_2(bp);
531 ND_PRINT(", port id: %u", port_id);
532 *len -= 2;
533 bp += 2;
534 }
535 static void
536 ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
537 {
538 uint8_t rsvd, gm_prio_1, gm_prio_2, gm_clk_cls, gm_clk_acc, time_src;
539 uint16_t origin_cur_utc, gm_clk_var, steps_removed;
540 uint64_t gm_clock_id;
541
542 ptp_print_timestamp(ndo, bp, len, p_origin_ts);
543 *len -= PTP_TIMESTAMP_LEN;
544 bp += PTP_TIMESTAMP_LEN;
545
546 /* origin cur utc */
547 origin_cur_utc = GET_BE_U_2(bp);
548 ND_PRINT(", origin cur utc:%u", origin_cur_utc);
549 *len -= 2;
550 bp += 2;
551
552 /* rsvd */
553 rsvd = GET_U_1(bp);
554 ND_PRINT(", rsvd: %u", rsvd);
555 *len -= 1;
556 bp += 1;
557
558 /* gm prio */
559 gm_prio_1 = GET_U_1(bp);
560 ND_PRINT(", gm priority_1: %u", gm_prio_1);
561 *len -= 1;
562 bp += 1;
563
564 /* GM clock class */
565 gm_clk_cls = GET_U_1(bp);
566 ND_PRINT(", gm clock class: %u", gm_clk_cls);
567 *len -= 1;
568 bp += 1;
569 /* GM clock accuracy */
570 gm_clk_acc = GET_U_1(bp);
571 ND_PRINT(", gm clock accuracy: %u", gm_clk_acc);
572 *len -= 1;
573 bp += 1;
574 /* GM clock variance */
575 gm_clk_var = GET_BE_U_2(bp);
576 ND_PRINT(", gm clock variance: %u", gm_clk_var);
577 *len -= 2;
578 bp += 2;
579 /* GM Prio 2 */
580 gm_prio_2 = GET_U_1(bp);
581 ND_PRINT(", gm priority_2: %u", gm_prio_2);
582 *len -= 1;
583 bp += 1;
584
585 /* GM Clock Identity */
586 gm_clock_id = GET_BE_U_8(bp);
587 ND_PRINT(", gm clock id: 0x%"PRIx64, gm_clock_id);
588 *len -= 8;
589 bp += 8;
590 /* steps removed */
591 steps_removed = GET_BE_U_2(bp);
592 ND_PRINT(", steps removed: %u", steps_removed);
593 *len -= 2;
594 bp += 2;
595 /* Time source */
596 time_src = GET_U_1(bp);
597 ND_PRINT(", time source: 0x%x", time_src);
598 *len -= 1;
599 bp += 1;
600
601 }
602
603 static const u_char *
604 ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
605 {
606 uint16_t port_id;
607 uint64_t port_identity;
608
609 /* port identity*/
610 port_identity = GET_BE_U_8(bp);
611 ND_PRINT(", port identity: 0x%"PRIx64, port_identity);
612 *len -= 8;
613 bp += 8;
614
615 /* port id */
616 port_id = GET_BE_U_2(bp);
617 ND_PRINT(", port id: %u", port_id);
618 *len -= 2;
619 bp += 2;
620
621 return bp;
622 }
623
624 static void
625 ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
626 {
627 bp = ptp_print_port_id(ndo, bp, len);
628 bp = print_field(ndo, "start boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
629 bp = print_field(ndo, "boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
630 bp = print_field(ndo, "flags:", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
631 bp = print_field(ndo, "reserved:", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
632 }