xref: /freebsd/contrib/tcpdump/print-ptp.c (revision e6083790f217ba7f89cd2957922bd45e35466359)
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 const u_char *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 const u_char *
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     return bp;
349 }
350 
351 static void
ptp_print_1(netdissect_options * ndo)352 ptp_print_1(netdissect_options *ndo)
353 {
354     ND_PRINT(" (not implemented)");
355 }
356 
357 static void
ptp_print_2(netdissect_options * ndo,const u_char * bp,u_int length)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
ptp_print(netdissect_options * ndo,const u_char * bp,u_int length)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
ptp_print_timestamp(netdissect_options * ndo,const u_char * bp,u_int * len,const char * stype)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
ptp_print_timestamp_identity(netdissect_options * ndo,const u_char * bp,u_int * len,const char * ttype)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
ptp_print_announce_msg(netdissect_options * ndo,const u_char * bp,u_int * len)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 
620 static const u_char *
ptp_print_port_id(netdissect_options * ndo,const u_char * bp,u_int * len)621 ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
622 {
623     uint16_t port_id;
624     uint64_t port_identity;
625 
626     /* port identity*/
627     port_identity = GET_BE_U_8(bp);
628     ND_PRINT(", port identity: 0x%"PRIx64, port_identity);
629     *len -= 8;
630     bp += 8;
631 
632     /* port id */
633     port_id = GET_BE_U_2(bp);
634     ND_PRINT(", port id: %u", port_id);
635     *len -= 2;
636     bp += 2;
637 
638     return bp;
639 }
640 
641 static void
ptp_print_mgmt_msg(netdissect_options * ndo,const u_char * bp,u_int * len)642 ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
643 {
644     bp = ptp_print_port_id(ndo, bp, len);
645     bp = print_field(ndo, "start boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
646     bp = print_field(ndo, "boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
647     bp = print_field(ndo, "flags:", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
648     bp = print_field(ndo, "reserved:", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
649 }
650