X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/fbaf18d80ac98a58a3b5067648d2eea63fb1c320..refs/heads/master:/print-ptp.c diff --git a/print-ptp.c b/print-ptp.c index 01ce53fd..1e474601 100644 --- a/print-ptp.c +++ b/print-ptp.c @@ -17,14 +17,12 @@ /* specification: https://standards.ieee.org/findstds/standard/1588-2008.html*/ -#ifdef HAVE_CONFIG_H #include -#endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" -#include +#include "timeval-operations.h" /* * PTP header @@ -36,7 +34,8 @@ * | domain No | rsvd1 | flag Field | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Correction NS | - * | Correction Sub NS | + * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | Correction Sub NS | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Reserved2 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -158,7 +157,7 @@ * | 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -176,42 +175,65 @@ * */ +/* 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 */ @@ -236,32 +258,26 @@ 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)); \ - } - -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 @@ -272,18 +288,16 @@ 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) { @@ -332,65 +346,70 @@ print_field(netdissect_options *ndo, const char *st, uint32_t flen, 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: @@ -417,7 +436,7 @@ static void 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: @@ -431,32 +450,42 @@ static void ptp_print_2(netdissect_options *ndo, const u_char *bp, u_int length) * 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 @@ -465,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_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; } @@ -482,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_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; } @@ -518,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_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; @@ -598,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); }