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
191static 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
218static 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
260static 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
277static const char *p_porigin_ts = "preciseOriginTimeStamp";
278static const char *p_origin_ts = "originTimeStamp";
279static 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
290static void ptp_print_1(netdissect_options *ndo);
291static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int len);
292
293static void ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype);
294static void ptp_print_timestamp_identity(netdissect_options *ndo, const u_char *bp, u_int *len, const char *ttype);
295static void ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
296static void ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len);
297static void ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
298
299static void
300print_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
350static void
351ptp_print_1(netdissect_options *ndo)
352{
353    ND_PRINT(" (not implemented)");
354}
355
356static void
357ptp_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 */
449void
450ptp_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
471invalid:
472    nd_print_invalid(ndo);
473}
474
475static void
476ptp_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}
494static void
495ptp_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}
528static void
529ptp_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}
606static void
607ptp_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
626static void
627ptp_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