/* 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 <string.h>
+#include "timeval-operations.h"
/*
* PTP header
* | 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 */
#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)); \
- }
-
-const char *p_porigin_ts = "preciseOriginTimeStamp";
-const char *p_origin_ts = "originTimeStamp";
-const char *p_recv_ts = "receiveTimeStamp";
+static const char *p_porigin_ts = "preciseOriginTimeStamp";
+static const char *p_origin_ts = "originTimeStamp";
+static const char *p_recv_ts = "receiveTimeStamp";
#define PTP_VER_1 0x1
#define PTP_VER_2 0x2
#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)
{
default:
break;
}
+
+ return bp;
}
static void
ptp_print_1(netdissect_options *ndo)
{
- ND_PRINT("ptp version 1: not implemented\n");
+ ND_PRINT(" (not implemented)");
}
-static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
+static void
+ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length)
{
u_int len = length;
- uint16_t msg_len, flags, seq_id;
- uint8_t foct, domain_no, msg_type, v1_compat, rsvd1, port_id, lm_int, control;
- uint32_t ns_corr, sns_corr, rsvd2;
+ uint16_t msg_len, flags, port_id, seq_id;
+ 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; 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:
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:
* PTP general message
*/
void
-ptp_print(netdissect_options *ndo, const u_char *bp, u_int len)
+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";
- if (len < PTP_HDR_LEN) {
- goto trunc;
- }
- 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;
case PTP_VER_2:
- ptp_print_2(ndo, bp, len);
+ ptp_print_2(ndo, bp, length);
break;
default:
- //ND_PRINT("ERROR: unknown-version\n");
+ ND_PRINT(" (unsupported)");
break;
}
return;
-trunc:
- nd_print_trunc(ndo);
- return;
+invalid:
+ nd_print_invalid(ndo);
}
static void
uint64_t secs;
uint32_t nsecs;
- ND_PRINT(", %s :", stype);
+ ND_PRINT(", %s:", stype);
/* sec time stamp 6 bytes */
- secs = GET_BE_U_2(bp) + GET_BE_U_4(bp+2);
- ND_PRINT(" %"PRIu64" seconds,", secs);
+ secs = GET_BE_U_6(bp);
+ 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;
}
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_2(bp) + GET_BE_U_4(bp+2);
- 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;
}
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_2(bp) + GET_BE_U_4(bp+2);
- 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;
/* 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);
}