xref: /freebsd/contrib/tcpdump/print-ptp.c (revision 1719886f6d08408b834d270c59ffcfd821c8f63a)
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  *  Signalling 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_SIGNALLING            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_SIGNALLING, "signalling 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_VERS_MASK       0xFF
235 #define PTP_V1_COMPAT       0x10
236 #define PTP_MSG_TYPE_MASK   0x0F
237 
238 /*mask based 2byte */
239 #define PTP_DOMAIN_MASK     0xFF00
240 #define PTP_RSVD1_MASK      0xFF
241 #define PTP_CONTROL_MASK    0xFF
242 #define PTP_LOGMSG_MASK     0xFF
243 
244 /* mask based on the flags 2 bytes */
245 
246 #define PTP_L161_MASK               0x1
247 #define PTP_L1_59_MASK              0x2
248 #define PTP_UTC_REASONABLE_MASK     0x4
249 #define PTP_TIMESCALE_MASK          0x8
250 #define PTP_TIME_TRACABLE_MASK      0x10
251 #define PTP_FREQUENCY_TRACABLE_MASK 0x20
252 #define PTP_ALTERNATE_MASTER_MASK   0x100
253 #define PTP_TWO_STEP_MASK           0x200
254 #define PTP_UNICAST_MASK            0x400
255 #define PTP_PROFILE_SPEC_1_MASK     0x1000
256 #define PTP_PROFILE_SPEC_2_MASK     0x2000
257 #define PTP_SECURITY_MASK           0x4000
258 #define PTP_FLAGS_UNKNOWN_MASK      0x18C0
259 
260 static const struct tok ptp_flag_values[] = {
261     { PTP_L161_MASK, "l1 61"},
262     { PTP_L1_59_MASK, "l1 59"},
263     { PTP_UTC_REASONABLE_MASK, "utc reasonable"},
264     { PTP_TIMESCALE_MASK, "timescale"},
265     { PTP_TIME_TRACABLE_MASK, "time tracable"},
266     { PTP_FREQUENCY_TRACABLE_MASK, "frequency tracable"},
267     { PTP_ALTERNATE_MASTER_MASK, "alternate master"},
268     { PTP_TWO_STEP_MASK, "two step"},
269     { PTP_UNICAST_MASK, "unicast"},
270     { PTP_PROFILE_SPEC_1_MASK, "profile specific 1"},
271     { PTP_PROFILE_SPEC_2_MASK, "profile specific 2"},
272     { PTP_SECURITY_MASK, "security mask"},
273     { PTP_FLAGS_UNKNOWN_MASK,  "unknown"},
274     {0, NULL}
275 };
276 
277 static const char *p_porigin_ts = "preciseOriginTimeStamp";
278 static const char *p_origin_ts = "originTimeStamp";
279 static const char *p_recv_ts = "receiveTimeStamp";
280 
281 #define PTP_VER_1 0x1
282 #define PTP_VER_2 0x2
283 
284 #define PTP_UCHAR_LEN  sizeof(uint8_t)
285 #define PTP_UINT16_LEN sizeof(uint16_t)
286 #define PTP_UINT32_LEN sizeof(uint32_t)
287 #define PTP_6BYTES_LEN sizeof(uint32_t)+sizeof(uint16_t)
288 #define PTP_UINT64_LEN sizeof(uint64_t)
289 
290 static void ptp_print_1(netdissect_options *ndo);
291 static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int len);
292 
293 static void ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype);
294 static void ptp_print_timestamp_identity(netdissect_options *ndo, const u_char *bp, u_int *len, const char *ttype);
295 static void ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
296 static void ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len);
297 static void ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
298 
299 static void
300 print_field(netdissect_options *ndo, const char *st, uint32_t flen,
301             const u_char *bp, u_int *len, uint8_t hex)
302 {
303     uint8_t u8_val;
304     uint16_t u16_val;
305     uint32_t u32_val;
306     uint64_t u64_val;
307 
308     switch(flen) {
309         case PTP_UCHAR_LEN:
310             u8_val = GET_U_1(bp);
311             ND_PRINT(", %s", st);
312             if (hex)
313                 ND_PRINT(" 0x%x", u8_val);
314             else
315                 ND_PRINT(" %u", u8_val);
316             *len -= 1; bp += 1;
317             break;
318         case PTP_UINT16_LEN:
319             u16_val = GET_BE_U_2(bp);
320             ND_PRINT(", %s", st);
321             if (hex)
322                 ND_PRINT(" 0x%x", u16_val);
323             else
324                 ND_PRINT(" %u", u16_val);
325             *len -= 2; bp += 2;
326             break;
327         case PTP_UINT32_LEN:
328             u32_val = GET_BE_U_4(bp);
329             ND_PRINT(", %s", st);
330             if (hex)
331                 ND_PRINT(" 0x%x", u32_val);
332             else
333                 ND_PRINT(" %u", u32_val);
334             *len -= 4; bp += 4;
335             break;
336         case PTP_UINT64_LEN:
337             u64_val = GET_BE_U_8(bp);
338             ND_PRINT(", %s", st);
339             if (hex)
340                 ND_PRINT(" 0x%"PRIx64, u64_val);
341             else
342                 ND_PRINT(" 0x%"PRIu64, u64_val);
343             *len -= 8; bp += 8;
344             break;
345         default:
346             break;
347     }
348 }
349 
350 static void
351 ptp_print_1(netdissect_options *ndo)
352 {
353     ND_PRINT(" (not implemented)");
354 }
355 
356 static void
357 ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
358 {
359     u_int len = length;
360     uint16_t msg_len, flags, port_id, seq_id;
361     uint8_t foct, domain_no, msg_type, v1_compat, rsvd1, lm_int, control;
362     uint64_t ns_corr;
363     uint16_t sns_corr;
364     uint32_t rsvd2;
365     uint64_t clk_id;
366 
367     foct = GET_U_1(bp);
368     v1_compat = foct & PTP_V1_COMPAT;
369     ND_PRINT(", v1 compat : %s", v1_compat?"yes":"no");
370     msg_type = foct & PTP_MSG_TYPE_MASK;
371     ND_PRINT(", msg type : %s", tok2str(ptp_msg_type, "Reserved", msg_type));
372 
373     /* msg length */
374     len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length : %u", msg_len);
375 
376     /* domain */
377     len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain : %u", domain_no);
378 
379     /* rsvd 1*/
380     rsvd1 = GET_BE_U_2(bp) & PTP_RSVD1_MASK;
381     ND_PRINT(", reserved1 : %u", rsvd1);
382 
383     /* flags */
384     len -= 2; bp += 2; flags = GET_BE_U_2(bp); ND_PRINT(", Flags [%s]", bittok2str(ptp_flag_values, "none", flags));
385 
386     /* correction NS (48 bits) */
387     len -= 2; bp += 2; ns_corr = GET_BE_U_6(bp); ND_PRINT(", NS correction : %"PRIu64, ns_corr);
388 
389     /* correction sub NS (16 bits) */
390     len -= 6; bp += 6; sns_corr = GET_BE_U_2(bp); ND_PRINT(", sub NS correction : %u", sns_corr);
391 
392     /* Reserved 2 */
393     len -= 2; bp += 2; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2 : %u", rsvd2);
394 
395     /* clock identity */
396     len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity : 0x%"PRIx64, clk_id);
397 
398     /* port identity */
399     len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id : %u", port_id);
400 
401     /* sequence ID */
402     len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id : %u", seq_id);
403 
404     /* control */
405     len -= 2; bp += 2; control = GET_U_1(bp) ;
406     ND_PRINT(", control : %u (%s)", control, tok2str(ptp_control_field, "Reserved", control));
407 
408     /* log message interval */
409     lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval : %u", lm_int); len -= 2; bp += 2;
410 
411     switch(msg_type) {
412         case M_SYNC:
413             ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
414             break;
415         case M_DELAY_REQ:
416             ptp_print_timestamp(ndo, bp, &len, p_origin_ts);
417             break;
418         case M_PDELAY_REQ:
419             ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
420             break;
421         case M_PDELAY_RESP:
422             ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
423             break;
424         case M_FOLLOW_UP:
425             ptp_print_timestamp(ndo, bp, &len, p_porigin_ts);
426             break;
427         case M_DELAY_RESP:
428             ptp_print_timestamp_identity(ndo, bp, &len, p_recv_ts);
429             break;
430         case M_PDELAY_RESP_FOLLOW_UP:
431             ptp_print_timestamp_identity(ndo, bp, &len, p_porigin_ts);
432             break;
433         case M_ANNOUNCE:
434             ptp_print_announce_msg(ndo, bp, &len);
435             break;
436         case M_SIGNALLING:
437             ptp_print_port_id(ndo, bp, &len);
438             break;
439         case M_MANAGEMENT:
440             ptp_print_mgmt_msg(ndo, bp, &len);
441             break;
442         default:
443             break;
444     }
445 }
446 /*
447  * PTP general message
448  */
449 void
450 ptp_print(netdissect_options *ndo, const u_char *bp, u_int length)
451 {
452     u_int vers;
453 
454     ndo->ndo_protocol = "ptp";
455     ND_LCHECK_U(length, PTP_HDR_LEN);
456     vers = GET_BE_U_2(bp) & PTP_VERS_MASK;
457     ND_PRINT("PTPv%u",vers);
458     switch(vers) {
459         case PTP_VER_1:
460             ptp_print_1(ndo);
461             break;
462         case PTP_VER_2:
463             ptp_print_2(ndo, bp, length);
464             break;
465         default:
466             //ND_PRINT("ERROR: unknown-version\n");
467             break;
468     }
469     return;
470 
471 invalid:
472     nd_print_invalid(ndo);
473 }
474 
475 static void
476 ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype)
477 {
478     uint64_t secs;
479     uint32_t nsecs;
480 
481     ND_PRINT(", %s :", stype);
482     /* sec time stamp 6 bytes */
483     secs = GET_BE_U_6(bp);
484     ND_PRINT(" %"PRIu64" seconds,", secs);
485     *len -= 6;
486     bp += 6;
487 
488     /* NS time stamp 4 bytes */
489     nsecs = GET_BE_U_4(bp);
490     ND_PRINT(" %u nanoseconds", nsecs);
491     *len -= 4;
492     bp += 4;
493 }
494 static void
495 ptp_print_timestamp_identity(netdissect_options *ndo,
496                             const u_char *bp, u_int *len, const char *ttype)
497 {
498     uint64_t secs;
499     uint32_t nsecs;
500     uint16_t port_id;
501     uint64_t port_identity;
502 
503     ND_PRINT(", %s :", ttype);
504     /* sec time stamp 6 bytes */
505     secs = GET_BE_U_6(bp);
506     ND_PRINT(" %"PRIu64" seconds,", secs);
507     *len -= 6;
508     bp += 6;
509 
510     /* NS time stamp 4 bytes */
511     nsecs = GET_BE_U_4(bp);
512     ND_PRINT(" %u nanoseconds", nsecs);
513     *len -= 4;
514     bp += 4;
515 
516     /* port identity*/
517     port_identity = GET_BE_U_8(bp);
518     ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
519     *len -= 8;
520     bp += 8;
521 
522     /* port id */
523     port_id = GET_BE_U_2(bp);
524     ND_PRINT(", port id : %u", port_id);
525     *len -= 2;
526     bp += 2;
527 }
528 static void
529 ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
530 {
531     uint8_t rsvd, gm_prio_1, gm_prio_2, gm_clk_cls, gm_clk_acc, time_src;
532     uint16_t origin_cur_utc, gm_clk_var, steps_removed;
533     uint64_t gm_clock_id;
534     uint64_t secs;
535     uint32_t nsecs;
536 
537     ND_PRINT(", %s :", p_origin_ts);
538     /* sec time stamp 6 bytes */
539     secs = GET_BE_U_6(bp);
540     ND_PRINT(" %"PRIu64" seconds", secs);
541     *len -= 6;
542     bp += 6;
543 
544     /* NS time stamp 4 bytes */
545     nsecs = GET_BE_U_4(bp);
546     ND_PRINT(" %u nanoseconds", nsecs);
547     *len -= 4;
548     bp += 4;
549 
550     /* origin cur utc */
551     origin_cur_utc = GET_BE_U_2(bp);
552     ND_PRINT(", origin cur utc :%u", origin_cur_utc);
553     *len -= 2;
554     bp += 2;
555 
556     /* rsvd */
557     rsvd = GET_U_1(bp);
558     ND_PRINT(", rsvd : %u", rsvd);
559     *len -= 1;
560     bp += 1;
561 
562     /* gm prio */
563     gm_prio_1 = GET_U_1(bp);
564     ND_PRINT(", gm priority_1 : %u", gm_prio_1);
565     *len -= 1;
566     bp += 1;
567 
568     /* GM clock class */
569     gm_clk_cls = GET_U_1(bp);
570     ND_PRINT(", gm clock class : %u", gm_clk_cls);
571     *len -= 1;
572     bp += 1;
573     /* GM clock accuracy */
574     gm_clk_acc = GET_U_1(bp);
575     ND_PRINT(", gm clock accuracy : %u", gm_clk_acc);
576     *len -= 1;
577     bp += 1;
578     /* GM clock variance */
579     gm_clk_var = GET_BE_U_2(bp);
580     ND_PRINT(", gm clock variance : %u", gm_clk_var);
581     *len -= 2;
582     bp += 2;
583     /* GM Prio 2 */
584     gm_prio_2 = GET_U_1(bp);
585     ND_PRINT(", gm priority_2 : %u", gm_prio_2);
586     *len -= 1;
587     bp += 1;
588 
589     /* GM Clock Identity */
590     gm_clock_id = GET_BE_U_8(bp);
591     ND_PRINT(", gm clock id : 0x%"PRIx64, gm_clock_id);
592     *len -= 8;
593     bp += 8;
594     /* steps removed */
595     steps_removed = GET_BE_U_2(bp);
596     ND_PRINT(", steps removed : %u", steps_removed);
597     *len -= 2;
598     bp += 2;
599     /* Time source */
600     time_src = GET_U_1(bp);
601     ND_PRINT(", time source : 0x%x", time_src);
602     *len -= 1;
603     bp += 1;
604 
605 }
606 static void
607 ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
608 {
609     uint16_t port_id;
610     uint64_t port_identity;
611 
612     /* port identity*/
613     port_identity = GET_BE_U_8(bp);
614     ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
615     *len -= 8;
616     bp += 8;
617 
618     /* port id */
619     port_id = GET_BE_U_2(bp);
620     ND_PRINT(", port id : %u", port_id);
621     *len -= 2;
622     bp += 2;
623 
624 }
625 
626 static void
627 ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
628 {
629     ptp_print_port_id(ndo, bp, len);
630     print_field(ndo, ", start boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
631     print_field(ndo, ", boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
632     print_field(ndo, ", flags ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
633     print_field(ndo, ", reserved ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
634 }
635