]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-ptp.c
CI: Add warning exemptions for Sun C (suncc-5.14) on Solaris 10
[tcpdump] / print-ptp.c
index f4ccbe9d03a0d3198d06a8ce4ea5f33366c88179..1e474601f5f1027d6bf2da8b4411e05c743dba3b 100644 (file)
 
 /* specification: https://standards.ieee.org/findstds/standard/1588-2008.html*/
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
 
 #include "netdissect-stdinc.h"
 #include "netdissect.h"
 #include "extract.h"
+#include "timeval-operations.h"
 
 /*
  * PTP header
@@ -35,7 +34,8 @@
  *    |  domain No    | rsvd1         |   flag Field                  |
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *    |                        Correction NS                          |
- *    |                      Correction Sub NS                        |
+ *    +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *    |                               |      Correction Sub NS        |
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *    |                           Reserved2                           |
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *    | Requesting Port Identity      |
  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
- *  Signalling Message (msg type=0xC)
+ *  Signaling Message (msg type=0xC)
  *     0                   1                   2                   3
  *     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
  *                                    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  */
 
+/* Values from IEEE1588-2008: 13.3.2.2 messageType (Enumeration4) */
 #define M_SYNC                  0x0
 #define M_DELAY_REQ             0x1
 #define M_PDELAY_REQ            0x2
 #define M_PDELAY_RESP           0x3
-#define M_OTHER                 0x5
 #define M_FOLLOW_UP             0x8
 #define M_DELAY_RESP            0x9
 #define M_PDELAY_RESP_FOLLOW_UP 0xA
 #define M_ANNOUNCE              0xB
-#define M_SIGNALLING            0xC
+#define M_SIGNALING             0xC
 #define M_MANAGEMENT            0xD
 
 static const struct tok ptp_msg_type[] = {
-    { M_SYNC ,"sync msg"},
-    { M_DELAY_REQ ,"delay req msg"},
-    { M_PDELAY_REQ ,"peer delay req msg"},
-    { M_PDELAY_RESP ,"peer delay resp msg"},
-    { M_OTHER, "Other"},
-    { M_FOLLOW_UP ,"follow up msg"},
-    { M_DELAY_RESP ,"delay resp msg"},
-    { M_PDELAY_RESP_FOLLOW_UP ,"pdelay resp fup msg"},
-    { M_ANNOUNCE ,"announce msg"},
-    { M_SIGNALLING ,"signalling msg"},
-    { M_MANAGEMENT ,"management msg"},
+    { M_SYNC, "sync msg"},
+    { M_DELAY_REQ, "delay req msg"},
+    { M_PDELAY_REQ, "peer delay req msg"},
+    { M_PDELAY_RESP, "peer delay resp msg"},
+    { M_FOLLOW_UP, "follow up msg"},
+    { M_DELAY_RESP, "delay resp msg"},
+    { M_PDELAY_RESP_FOLLOW_UP, "pdelay resp fup msg"},
+    { M_ANNOUNCE, "announce msg"},
+    { M_SIGNALING, "signaling msg"},
+    { M_MANAGEMENT, "management msg"},
     { 0, NULL}
 };
 
+/* Values from IEEE1588-2008: 13.3.2.10 controlField (UInteger8) */
+/*
+ * The use of this field by the receiver is deprecated.
+ * NOTE-This field is provided for compatibility with hardware designed
+ * to conform to version 1 of this standard.
+ */
+#define C_SYNC              0x0
+#define C_DELAY_REQ         0x1
+#define C_FOLLOW_UP         0x2
+#define C_DELAY_RESP        0x3
+#define C_MANAGEMENT        0x4
+#define C_OTHER             0x5
+
+static const struct tok ptp_control_field[] = {
+    { C_SYNC, "Sync"},
+    { C_DELAY_REQ, "Delay_Req"},
+    { C_FOLLOW_UP, "Follow_Up"},
+    { C_DELAY_RESP, "Delay_Resp"},
+    { C_MANAGEMENT, "Management"},
+    { C_OTHER, "Other"},
+    { 0, NULL}
+};
 
 #define PTP_TRUE 1
 #define PTP_FALSE !PTP_TRUE
 
 #define PTP_HDR_LEN         0x22
+#define PTP_TIMESTAMP_LEN   10U
 
 /* mask based on the first byte */
-#define PTP_VERS_MASK       0xFF
-#define PTP_V1_COMPAT       0x10
+#define PTP_MAJOR_VERS_MASK 0x0F
+#define PTP_MINOR_VERS_MASK 0xF0
+#define PTP_MAJOR_SDO_ID_MASK   0xF0
 #define PTP_MSG_TYPE_MASK   0x0F
 
 /*mask based 2byte */
@@ -235,29 +258,23 @@ static const struct tok ptp_msg_type[] = {
 #define PTP_SECURITY_MASK           0x4000
 #define PTP_FLAGS_UNKNOWN_MASK      0x18C0
 
-
 static const struct tok ptp_flag_values[] = {
-    { PTP_L161_MASK ,"l1 61"},
-    { PTP_L1_59_MASK ,"l1 59"},
-    { PTP_UTC_REASONABLE_MASK ,"utc reasonable"},
-    { PTP_TIMESCALE_MASK ,"timescale"},
-    { PTP_TIME_TRACABLE_MASK ,"time tracable"},
-    { PTP_FREQUENCY_TRACABLE_MASK ,"frequency tracable"},
-    { PTP_ALTERNATE_MASTER_MASK ,"alternate master"},
-    { PTP_TWO_STEP_MASK ,"two step"},
-    { PTP_UNICAST_MASK ,"unicast"},
-    { PTP_PROFILE_SPEC_1_MASK ,"profile specific 1"},
-    { PTP_PROFILE_SPEC_2_MASK ,"profile specific 2"},
-    { PTP_SECURITY_MASK ,"security mask"},
-    { PTP_FLAGS_UNKNOWN_MASK , "unknown"},
+    { PTP_L161_MASK"l1 61"},
+    { PTP_L1_59_MASK"l1 59"},
+    { PTP_UTC_REASONABLE_MASK"utc reasonable"},
+    { PTP_TIMESCALE_MASK"timescale"},
+    { PTP_TIME_TRACABLE_MASK"time tracable"},
+    { PTP_FREQUENCY_TRACABLE_MASK"frequency tracable"},
+    { PTP_ALTERNATE_MASTER_MASK"alternate master"},
+    { PTP_TWO_STEP_MASK"two step"},
+    { PTP_UNICAST_MASK"unicast"},
+    { PTP_PROFILE_SPEC_1_MASK"profile specific 1"},
+    { PTP_PROFILE_SPEC_2_MASK"profile specific 2"},
+    { PTP_SECURITY_MASK"security mask"},
+    { PTP_FLAGS_UNKNOWN_MASK "unknown"},
     {0, NULL}
 };
 
-#define PTP_PRINT_MSG_TYPE(e) \
-        { \
-            ND_PRINT("(%s)", tok2str(ptp_msg_type, "unknown", e)); \
-        }
-
 static const char *p_porigin_ts = "preciseOriginTimeStamp";
 static const char *p_origin_ts = "originTimeStamp";
 static const char *p_recv_ts = "receiveTimeStamp";
@@ -271,18 +288,16 @@ static const char *p_recv_ts = "receiveTimeStamp";
 #define PTP_6BYTES_LEN sizeof(uint32_t)+sizeof(uint16_t)
 #define PTP_UINT64_LEN sizeof(uint64_t)
 
-
-
 static void ptp_print_1(netdissect_options *ndo);
 static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int len);
 
 static void ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const char *stype);
 static void ptp_print_timestamp_identity(netdissect_options *ndo, const u_char *bp, u_int *len, const char *ttype);
 static void ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
-static void ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len);
+static const u_char *ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len);
 static void ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len);
 
-static void
+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)
 {
@@ -331,6 +346,8 @@ print_field(netdissect_options *ndo, const char *st, uint32_t flen,
         default:
             break;
     }
+
+    return bp;
 }
 
 static void
@@ -344,53 +361,55 @@ ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
 {
     u_int len = length;
     uint16_t msg_len, flags, port_id, seq_id;
-    uint8_t foct, domain_no, msg_type, v1_compat, rsvd1, lm_int, control;
-    uint32_t ns_corr, sns_corr, rsvd2;
+    uint8_t foct, domain_no, msg_type, major_sdo_id, rsvd1, lm_int, control;
+    uint64_t ns_corr;
+    uint16_t sns_corr;
+    uint32_t rsvd2;
     uint64_t clk_id;
 
     foct = GET_U_1(bp);
-    v1_compat = foct & PTP_V1_COMPAT;
-    ND_PRINT(", v1 compat : %s", v1_compat?"yes":"no");
+    major_sdo_id = (foct & PTP_MAJOR_SDO_ID_MASK) >> 4;
+    ND_PRINT(", majorSdoId: 0x%x", major_sdo_id);
     msg_type = foct & PTP_MSG_TYPE_MASK;
-    ND_PRINT(", msg type : %s", tok2str(ptp_msg_type, "none", msg_type));
+    ND_PRINT(", msg type: %s", tok2str(ptp_msg_type, "Reserved", msg_type));
 
     /* msg length */
-    len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length : %u", msg_len);
+    len -= 2; bp += 2; msg_len = GET_BE_U_2(bp); ND_PRINT(", length: %u", msg_len);
 
     /* domain */
-    len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain : %u", domain_no);
+    len -= 2; bp += 2; domain_no = (GET_BE_U_2(bp) & PTP_DOMAIN_MASK) >> 8; ND_PRINT(", domain: %u", domain_no);
 
     /* rsvd 1*/
     rsvd1 = GET_BE_U_2(bp) & PTP_RSVD1_MASK;
-    ND_PRINT(", reserved1 : %u", rsvd1);
+    ND_PRINT(", reserved1: %u", rsvd1);
 
     /* flags */
     len -= 2; bp += 2; flags = GET_BE_U_2(bp); ND_PRINT(", Flags [%s]", bittok2str(ptp_flag_values, "none", flags));
 
-    /* correction NS */
-    len -= 2; bp += 2; ns_corr = GET_BE_U_4(bp); ND_PRINT(", NS correction : %u", ns_corr);
+    /* correction NS (48 bits) */
+    len -= 2; bp += 2; ns_corr = GET_BE_U_6(bp); ND_PRINT(", NS correction: %"PRIu64, ns_corr);
 
-    /* correction sub NS */
-    len -= 4; bp += 4; sns_corr = GET_BE_U_4(bp); ND_PRINT(", sub NS correction : %u", sns_corr);
+    /* correction sub NS (16 bits) */
+    len -= 6; bp += 6; sns_corr = GET_BE_U_2(bp); ND_PRINT(", sub NS correction: %u", sns_corr);
 
     /* Reserved 2 */
-    len -= 4; bp += 4; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2 : %u", rsvd2);
+    len -= 2; bp += 2; rsvd2 = GET_BE_U_4(bp); ND_PRINT(", reserved2: %u", rsvd2);
 
     /* clock identity */
-    len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity : 0x%"PRIx64, clk_id);
+    len -= 4; bp += 4; clk_id = GET_BE_U_8(bp); ND_PRINT(", clock identity: 0x%"PRIx64, clk_id);
 
     /* port identity */
-    len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id : %u", port_id);
+    len -= 8; bp += 8; port_id = GET_BE_U_2(bp); ND_PRINT(", port id: %u", port_id);
 
     /* sequence ID */
-    len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id : %u", seq_id);
+    len -= 2; bp += 2; seq_id = GET_BE_U_2(bp); ND_PRINT(", seq id: %u", seq_id);
 
     /* control */
     len -= 2; bp += 2; control = GET_U_1(bp) ;
-    ND_PRINT(", control : %u (%s)", control, tok2str(ptp_msg_type, "none", control));
+    ND_PRINT(", control: %u (%s)", control, tok2str(ptp_control_field, "Reserved", control));
 
     /* log message interval */
-    lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval : %u", lm_int); len -= 2; bp += 2;
+    lm_int = GET_BE_U_2(bp) & PTP_LOGMSG_MASK; ND_PRINT(", log message interval: %u", lm_int); len -= 2; bp += 2;
 
     switch(msg_type) {
         case M_SYNC:
@@ -417,7 +436,7 @@ ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
         case M_ANNOUNCE:
             ptp_print_announce_msg(ndo, bp, &len);
             break;
-        case M_SIGNALLING:
+        case M_SIGNALING:
             ptp_print_port_id(ndo, bp, &len);
             break;
         case M_MANAGEMENT:
@@ -433,13 +452,26 @@ ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
 void
 ptp_print(netdissect_options *ndo, const u_char *bp, u_int length)
 {
-    u_int vers;
-
+    u_int major_vers;
+    u_int minor_vers;
+
+    /* In 1588-2019, a minorVersionPTP field has been created in the common PTP
+     * message header, from a previously reserved field. Implementations
+     * compatible to the 2019 edition shall indicate a versionPTP field value
+     * of 2 and minorVersionPTP field value of 1, indicating that this is PTP
+     * version 2.1.
+     */
     ndo->ndo_protocol = "ptp";
-    ND_LCHECK_U(length, PTP_HDR_LEN);
-    vers = GET_BE_U_2(bp) & PTP_VERS_MASK;
-    ND_PRINT("PTPv%u",vers);
-    switch(vers) {
+    nd_print_protocol_caps(ndo);
+    ND_ICHECK_U(length, <, PTP_HDR_LEN);
+    major_vers = GET_BE_U_2(bp) & PTP_MAJOR_VERS_MASK;
+    minor_vers = (GET_BE_U_2(bp) & PTP_MINOR_VERS_MASK) >> 4;
+    if (minor_vers)
+           ND_PRINT("v%u.%u", major_vers, minor_vers);
+    else
+           ND_PRINT("v%u", major_vers);
+
+    switch(major_vers) {
         case PTP_VER_1:
             ptp_print_1(ndo);
             break;
@@ -447,7 +479,7 @@ ptp_print(netdissect_options *ndo, const u_char *bp, u_int length)
             ptp_print_2(ndo, bp, length);
             break;
         default:
-            //ND_PRINT("ERROR: unknown-version\n");
+            ND_PRINT(" (unsupported)");
             break;
     }
     return;
@@ -462,16 +494,18 @@ ptp_print_timestamp(netdissect_options *ndo, const u_char *bp, u_int *len, const
     uint64_t secs;
     uint32_t nsecs;
 
-    ND_PRINT(", %s :", stype);
+    ND_PRINT(", %s:", stype);
     /* sec time stamp 6 bytes */
     secs = GET_BE_U_6(bp);
-    ND_PRINT(" %"PRIu64" seconds,", secs);
+    ND_PRINT(" %"PRIu64".", secs);
     *len -= 6;
     bp += 6;
 
     /* NS time stamp 4 bytes */
     nsecs = GET_BE_U_4(bp);
-    ND_PRINT(" %u nanoseconds", nsecs);
+    ND_PRINT("%09u seconds", nsecs);
+    if (nsecs > ND_NANO_PER_SEC - 1)
+        ND_PRINT(" " ND_INVALID_NANO_SEC_STR);
     *len -= 4;
     bp += 4;
 }
@@ -479,33 +513,22 @@ static void
 ptp_print_timestamp_identity(netdissect_options *ndo,
                             const u_char *bp, u_int *len, const char *ttype)
 {
-    uint64_t secs;
-    uint32_t nsecs;
     uint16_t port_id;
     uint64_t port_identity;
 
-    ND_PRINT(", %s :", ttype);
-    /* sec time stamp 6 bytes */
-    secs = GET_BE_U_6(bp);
-    ND_PRINT(" %"PRIu64" seconds,", secs);
-    *len -= 6;
-    bp += 6;
-
-    /* NS time stamp 4 bytes */
-    nsecs = GET_BE_U_4(bp);
-    ND_PRINT(" %u nanoseconds", nsecs);
-    *len -= 4;
-    bp += 4;
+    ptp_print_timestamp(ndo, bp, len, ttype);
+    *len -= PTP_TIMESTAMP_LEN;
+    bp += PTP_TIMESTAMP_LEN;
 
     /* port identity*/
     port_identity = GET_BE_U_8(bp);
-    ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
+    ND_PRINT(", port identity: 0x%"PRIx64, port_identity);
     *len -= 8;
     bp += 8;
 
     /* port id */
     port_id = GET_BE_U_2(bp);
-    ND_PRINT(", port id : %u", port_id);
+    ND_PRINT(", port id: %u", port_id);
     *len -= 2;
     bp += 2;
 }
@@ -515,79 +538,69 @@ ptp_print_announce_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
     uint8_t rsvd, gm_prio_1, gm_prio_2, gm_clk_cls, gm_clk_acc, time_src;
     uint16_t origin_cur_utc, gm_clk_var, steps_removed;
     uint64_t gm_clock_id;
-    uint64_t secs;
-    uint32_t nsecs;
 
-    ND_PRINT(", %s :", p_origin_ts);
-    /* sec time stamp 6 bytes */
-    secs = GET_BE_U_6(bp);
-    ND_PRINT(" %"PRIu64" seconds", secs);
-    *len -= 6;
-    bp += 6;
-
-    /* NS time stamp 4 bytes */
-    nsecs = GET_BE_U_4(bp);
-    ND_PRINT(" %u nanoseconds", nsecs);
-    *len -= 4;
-    bp += 4;
+    ptp_print_timestamp(ndo, bp, len, p_origin_ts);
+    *len -= PTP_TIMESTAMP_LEN;
+    bp += PTP_TIMESTAMP_LEN;
 
     /* origin cur utc */
     origin_cur_utc = GET_BE_U_2(bp);
-    ND_PRINT(", origin cur utc :%u", origin_cur_utc);
+    ND_PRINT(", origin cur utc:%u", origin_cur_utc);
     *len -= 2;
     bp += 2;
 
     /* rsvd */
     rsvd = GET_U_1(bp);
-    ND_PRINT(", rsvd : %u", rsvd);
+    ND_PRINT(", rsvd: %u", rsvd);
     *len -= 1;
     bp += 1;
 
     /* gm prio */
     gm_prio_1 = GET_U_1(bp);
-    ND_PRINT(", gm priority_1 : %u", gm_prio_1);
+    ND_PRINT(", gm priority_1: %u", gm_prio_1);
     *len -= 1;
     bp += 1;
 
     /* GM clock class */
     gm_clk_cls = GET_U_1(bp);
-    ND_PRINT(", gm clock class : %u", gm_clk_cls);
+    ND_PRINT(", gm clock class: %u", gm_clk_cls);
     *len -= 1;
     bp += 1;
     /* GM clock accuracy */
     gm_clk_acc = GET_U_1(bp);
-    ND_PRINT(", gm clock accuracy : %u", gm_clk_acc);
+    ND_PRINT(", gm clock accuracy: %u", gm_clk_acc);
     *len -= 1;
     bp += 1;
     /* GM clock variance */
     gm_clk_var = GET_BE_U_2(bp);
-    ND_PRINT(", gm clock variance : %u", gm_clk_var);
+    ND_PRINT(", gm clock variance: %u", gm_clk_var);
     *len -= 2;
     bp += 2;
     /* GM Prio 2 */
     gm_prio_2 = GET_U_1(bp);
-    ND_PRINT(", gm priority_2 : %u", gm_prio_2);
+    ND_PRINT(", gm priority_2: %u", gm_prio_2);
     *len -= 1;
     bp += 1;
 
     /* GM Clock Identity */
     gm_clock_id = GET_BE_U_8(bp);
-    ND_PRINT(", gm clock id : 0x%"PRIx64, gm_clock_id);
+    ND_PRINT(", gm clock id: 0x%"PRIx64, gm_clock_id);
     *len -= 8;
     bp += 8;
     /* steps removed */
     steps_removed = GET_BE_U_2(bp);
-    ND_PRINT(", steps removed : %u", steps_removed);
+    ND_PRINT(", steps removed: %u", steps_removed);
     *len -= 2;
     bp += 2;
     /* Time source */
     time_src = GET_U_1(bp);
-    ND_PRINT(", time source : 0x%x", time_src);
+    ND_PRINT(", time source: 0x%x", time_src);
     *len -= 1;
     bp += 1;
 
 }
-static void
+
+static const u_char *
 ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
 {
     uint16_t port_id;
@@ -595,24 +608,25 @@ ptp_print_port_id(netdissect_options *ndo, const u_char *bp, u_int *len)
 
     /* port identity*/
     port_identity = GET_BE_U_8(bp);
-    ND_PRINT(", port identity : 0x%"PRIx64, port_identity);
+    ND_PRINT(", port identity: 0x%"PRIx64, port_identity);
     *len -= 8;
     bp += 8;
 
     /* port id */
     port_id = GET_BE_U_2(bp);
-    ND_PRINT(", port id : %u", port_id);
+    ND_PRINT(", port id: %u", port_id);
     *len -= 2;
     bp += 2;
 
+    return bp;
 }
 
 static void
 ptp_print_mgmt_msg(netdissect_options *ndo, const u_char *bp, u_int *len)
 {
-    ptp_print_port_id(ndo, bp, len);
-    print_field(ndo, ", start boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
-    print_field(ndo, ", boundary hops ", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
-    print_field(ndo, ", flags ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
-    print_field(ndo, ", reserved ", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
+    bp = ptp_print_port_id(ndo, bp, len);
+    bp = print_field(ndo, "start boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
+    bp = print_field(ndo, "boundary hops:", PTP_UCHAR_LEN, bp, len, PTP_FALSE);
+    bp = print_field(ndo, "flags:", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
+    bp = print_field(ndo, "reserved:", PTP_UCHAR_LEN, bp, len, PTP_TRUE);
 }