diff --git a/doc/README.dissector b/doc/README.dissector index 3a722cb87f..f3b1d61897 100644 --- a/doc/README.dissector +++ b/doc/README.dissector @@ -1598,15 +1598,57 @@ For FT_ABSOLUTE_TIME fields, the encoding specifies the form in which the time stamp is specified, as well as its byte order. The time stamp encodings that are currently supported are: - ENC_TIME_TIMESPEC - seconds (4 bytes) and nanoseconds (4 bytes) - of time since January 1, 1970, midnight UTC. - (If the field length is 4, then nanosecs is defaulted to 0). + ENC_TIME_TIMESPEC - 8 bytes; the first 4 bytes are seconds since + the UN*X epoch (1970-01-01 00:00:00 UTC) and the next 4 bytes + are nanoseconds since that second. (I.e., a UN*X struct + timespec with a 4-byte time_t.) + + ENC_TIME_NTP - 8 bytes; the first 4 bytes are seconds since the NTP + epoch (1901-01-01 00:00:00 GMT) and the next 4 bytes are 1/2^32's of + a second since that second. (I.e., a 64-bit count of 1/2^32's of a + second since the NTP epoch, with the upper 32 bits first and the + lower 32 bits second, even when little-endian.) + + ENC_TIME_TOD - 8 bytes, as a count of microseconds since the System/3x0 + and z/Architecture epoch (1900-01-01 00:00:00 GMT). + + ENC_TIME_RTPS - 8 bytes; the first 4 bytes are seconds since the UN*X + epoch and the next 4 bytes are are 1/2^32's of a second since that + second. (I.e., it's the offspring of a mating between UN*X time and + NTP time.) It's used by the Object Management Group's Real-Time + Publish-Subscribe Wire Protocol for the Data Distribution Service. + + ENC_TIME_TIMEVAL - 8 bytes; the first 4 bytes are seconds since the + UN*X epoch and the next 4 bytes are microseconds since that + second. (I.e., a UN*X struct timeval with a 4-byte time_t.) + + ENC_TIME_SECS - 4 to 8 bytes, representing a value in seconds since + the UN*X epoch. + + ENC_TIME_MSECS - 6 to 8 bytes, representing a value in milliseconds + since the UN*X epoch. + + ENC_TIME_SECS_NTP - 4 bytes, representing a count of seconds since + the NTP epoch. (I.e., seconds since the NTP epoch.) + + ENC_TIME_RFC_3971 - 8 bytes, representing a count of 1/64ths of a + second since the UN*X epoch; see section 5.3.1 "Timestamp Option" + in RFC 3971. - ENC_TIME_NTP - an NTP timestamp, represented as a 64-bit - unsigned fixed-point number, in seconds relative to 0h - on 1 January 1900. The integer part is in the first 32 - bits and the fraction part in the last 32 bits. +For FT_RELATIVE_TIME fields, the encoding specifies the form in which +the time stamp is specified, as well as its byte order. The time stamp +encodings that are currently supported are: + ENC_TIME_TIMESPEC - 8 bytes; the first 4 bytes are seconds and the + next 4 bytes are nanoseconds. + + ENC_TIME_TIMEVAL - 8 bytes; the first 4 bytes are seconds and the + next 4 bytes are microseconds. + + ENC_TIME_SECS - 4 to 8 bytes, representing a value in seconds. + + ENC_TIME_MSECS - 6 to 8 bytes, representing a value in milliseconds. + For other types, there is no support for proto_tree_add_item(). Now that definitions of fields have detailed information about bitfield diff --git a/epan/dissectors/packet-bitcoin.c b/epan/dissectors/packet-bitcoin.c index fa621ad8b1..319d03ea56 100644 --- a/epan/dissectors/packet-bitcoin.c +++ b/epan/dissectors/packet-bitcoin.c @@ -902,7 +902,7 @@ dissect_bitcoin_msg_addr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree ti = proto_tree_add_item(tree, &hfi_msg_addr_address, tvb, offset, 30, ENC_NA); subtree = create_address_tree(tvb, ti, offset+4); - proto_tree_add_item(subtree, &hfi_msg_addr_timestamp, tvb, offset, 4, ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN); + proto_tree_add_item(subtree, &hfi_msg_addr_timestamp, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN); offset += 26; offset += 4; } @@ -1274,7 +1274,7 @@ dissect_bitcoin_msg_block(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v proto_tree_add_item(tree, &hfi_msg_block_merkle_root, tvb, offset, 32, ENC_NA); offset += 32; - proto_tree_add_item(tree, &hfi_msg_block_time, tvb, offset, 4, ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree, &hfi_msg_block_time, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, &hfi_msg_block_bits, tvb, offset, 4, ENC_LITTLE_ENDIAN); @@ -1335,7 +1335,7 @@ dissect_bitcoin_msg_headers(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *t proto_tree_add_item(subtree, &hfi_msg_headers_merkle_root, tvb, offset, 32, ENC_NA); offset += 32; - proto_tree_add_item(subtree, &hfi_msg_headers_time, tvb, offset, 4, ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN); + proto_tree_add_item(subtree, &hfi_msg_headers_time, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(subtree, &hfi_msg_headers_bits, tvb, offset, 4, ENC_LITTLE_ENDIAN); @@ -1488,7 +1488,7 @@ dissect_bitcoin_msg_merkleblock(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tre proto_tree_add_item(tree, &hfi_msg_merkleblock_merkle_root, tvb, offset, 32, ENC_NA); offset += 32; - proto_tree_add_item(tree, &hfi_msg_merkleblock_time, tvb, offset, 4, ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree, &hfi_msg_merkleblock_time, tvb, offset, 4, ENC_TIME_SECS|ENC_LITTLE_ENDIAN); offset += 4; proto_tree_add_item(tree, &hfi_msg_merkleblock_bits, tvb, offset, 4, ENC_LITTLE_ENDIAN); diff --git a/epan/dissectors/packet-capwap.c b/epan/dissectors/packet-capwap.c index b78c973c17..1cc9868ae8 100644 --- a/epan/dissectors/packet-capwap.c +++ b/epan/dissectors/packet-capwap.c @@ -2260,7 +2260,7 @@ hf_capwap_msg_element_type_ac_descriptor_dtls_policy, ett_capwap_ac_descriptor_d "AC Timestamp length %u wrong, must be = 4", optlen); break; } - proto_tree_add_item(sub_msg_element_type_tree, hf_capwap_msg_element_type_ac_timestamp, tvb, offset + 4, 4, ENC_TIME_NTP|ENC_BIG_ENDIAN); + proto_tree_add_item(sub_msg_element_type_tree, hf_capwap_msg_element_type_ac_timestamp, tvb, offset + 4, 4, ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN); break; case TYPE_ADD_STATION:{ /* Add Station (8) */ diff --git a/epan/dissectors/packet-diameter.c b/epan/dissectors/packet-diameter.c index de8efcbf44..061ed323ad 100644 --- a/epan/dissectors/packet-diameter.c +++ b/epan/dissectors/packet-diameter.c @@ -912,7 +912,7 @@ time_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb, diam_sub_dis_t *diam_sub_d if (c->tree) { label = (char *)wmem_alloc(wmem_packet_scope(), ITEM_LABEL_LENGTH+1); - pi = proto_tree_add_item(c->tree, (a->hf_value), tvb, 0, 4, ENC_TIME_NTP|ENC_BIG_ENDIAN); + pi = proto_tree_add_item(c->tree, (a->hf_value), tvb, 0, 4, ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN); proto_item_fill_label(PITEM_FINFO(pi), label); label = strstr(label,": ")+2; } diff --git a/epan/dissectors/packet-dns.c b/epan/dissectors/packet-dns.c index c8a3408e90..8674373cd9 100644 --- a/epan/dissectors/packet-dns.c +++ b/epan/dissectors/packet-dns.c @@ -3427,7 +3427,7 @@ dissect_dns_answer(tvbuff_t *tvb, int offsetx, int dns_data_offset, proto_tree_add_string(rr_tree, hf_dns_tsig_algorithm_name, tvb, cur_offset, used_bytes, name_out); cur_offset += used_bytes; - ti = proto_tree_add_item(rr_tree, hf_dns_tsig_time_signed ,tvb, cur_offset, 6, ENC_NA); + ti = proto_tree_add_item(rr_tree, hf_dns_tsig_time_signed ,tvb, cur_offset, 6, ENC_TIME_SECS|ENC_BIG_ENDIAN); if(tvb_get_ntohs(tvb, cur_offset)) /* Time High */ { proto_item_append_text(ti, " (high bits set)"); diff --git a/epan/dissectors/packet-erf.c b/epan/dissectors/packet-erf.c index bfcb930835..14f4bd73a2 100644 --- a/epan/dissectors/packet-erf.c +++ b/epan/dissectors/packet-erf.c @@ -2442,7 +2442,7 @@ dissect_meta_record_tags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { * little endian. */ /* - * FIXME: ENC_TIME_NTP(_BASE_ZERO) | ENC_LITTLE_ENDIAN only swaps the + * FIXME: ENC_TIME_NTP | ENC_LITTLE_ENDIAN only swaps the * upper and lower 32 bits. Is that a bug or by design? Should add * a 'PTP" variant that doesn't round to microseconds and use that * here. For now do by hand. diff --git a/epan/dissectors/packet-icmpv6.c b/epan/dissectors/packet-icmpv6.c index 746e57d666..546acad79e 100644 --- a/epan/dissectors/packet-icmpv6.c +++ b/epan/dissectors/packet-icmpv6.c @@ -1844,7 +1844,7 @@ dissect_icmpv6_nd_opt(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree * remaining 16 bits indicate the number of 1/64K fractions of a * second. */ - proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_timestamp, tvb, opt_offset + 2, 4, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); + proto_tree_add_item(icmp6opt_tree, hf_icmpv6_opt_timestamp, tvb, opt_offset, 8, ENC_TIME_RFC_3971|ENC_BIG_ENDIAN); opt_offset += 8; break; case ND_OPT_NONCE: /* Nonce option (14) */ diff --git a/epan/dissectors/packet-netflow.c b/epan/dissectors/packet-netflow.c index 5de27cbf62..797cca7ec7 100644 --- a/epan/dissectors/packet-netflow.c +++ b/epan/dissectors/packet-netflow.c @@ -5666,6 +5666,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, break; case 37013: /* timestamp_interval */ + /* XXX - what format is this in? */ ti = proto_tree_add_item(pdutree, hf_cflow_timestamp_interval, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6183,6 +6184,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, break; case (NTOP_BASE + 151): /* RTP_FIRST_TS */ case ((VENDOR_NTOP << 16) | 151): /* RTP_FIRST_TS */ + /* XXX - is this an NTP timestamp? */ ti = proto_tree_add_item(pdutree, hf_pie_ntop_rtp_first_ts, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6193,6 +6195,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, break; case (NTOP_BASE + 153): /* RTP_LAST_TS */ case ((VENDOR_NTOP << 16) | 153): /* RTP_LAST_TS */ + /* XXX - is this an NTP timestamp? */ ti = proto_tree_add_item(pdutree, hf_pie_ntop_rtp_last_ts, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6367,6 +6370,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, tvb, offset, length, ENC_BIG_ENDIAN); break; case ((VENDOR_PLIXER << 16) | 111): /* origination_time */ + /* XXX - what format is this? */ ti = proto_tree_add_item(pdutree, hf_pie_plixer_origination_time, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6395,6 +6399,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, tvb, offset, length, gen_str); break; case ((VENDOR_PLIXER << 16) | 117): /* date_time */ + /* XXX - what format is this? */ ti = proto_tree_add_item(pdutree, hf_pie_plixer_date_time, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6840,10 +6845,18 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, tvb, offset, length, ENC_BIG_ENDIAN); break; case ((VENDOR_NETSCALER << 16) | 223): + /* + * XXX - this says "sec"; is it just seconds since the UN*X epoch, + * i.e. should it be ENC_TIME_SECS? + */ ti = proto_tree_add_item(pdutree, hf_pie_netscaler_icasessionupdatebeginsec, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; case ((VENDOR_NETSCALER << 16) | 224): + /* + * XXX - this says "sec"; is it just seconds since the UN*X epoch, + * i.e. should it be ENC_TIME_SECS? + */ ti = proto_tree_add_item(pdutree, hf_pie_netscaler_icasessionupdateendsec, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6904,6 +6917,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, tvb, offset, length, ENC_UTF_8|ENC_NA); break; case ((VENDOR_NETSCALER << 16) | 239): + /* XXX - what format is this? */ ti = proto_tree_add_item(pdutree, hf_pie_netscaler_applicationstartuptime, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -6964,10 +6978,12 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, tvb, offset, length, ENC_BIG_ENDIAN); break; case ((VENDOR_NETSCALER << 16) | 254): + /* XXX - what format is this? */ ti = proto_tree_add_item(pdutree, hf_pie_netscaler_icanetworkupdatestarttime, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; case ((VENDOR_NETSCALER << 16) | 255): + /* XXX - what format is this? */ ti = proto_tree_add_item(pdutree, hf_pie_netscaler_icanetworkupdateendtime, tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); break; @@ -7032,7 +7048,7 @@ dissect_v9_v10_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdutree, /* START Barracuda Communications */ case ((VENDOR_BARRACUDA << 16) | 1): ti = proto_tree_add_item(pdutree, hf_pie_barracuda_timestamp, - tvb, offset, length, ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN); + tvb, offset, length, ENC_TIME_SECS|ENC_BIG_ENDIAN); break; case ((VENDOR_BARRACUDA << 16) | 2): ti = proto_tree_add_item(pdutree, hf_pie_barracuda_logop, diff --git a/epan/dissectors/packet-reload.c b/epan/dissectors/packet-reload.c index 2eebdf735d..0268e1fc88 100644 --- a/epan/dissectors/packet-reload.c +++ b/epan/dissectors/packet-reload.c @@ -22,12 +22,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Please refer to the following specs for protocol detail: - * - draft-ietf-p2psip-base-18 - * - draft-ietf-p2psip-sip-06 - * - draft-ietf-p2psip-service-discovery-03 - * - draft-ietf-p2psip-self-tuning-04 - * - draft-ietf-p2psip-diagnostics-10 - * - draft-zong-p2psip-drr-01 + * - RFC 6940 + * - RFC 7904 + * - RFC 7374 + * - RFC 7363 + * - RFC 7851 + * - RFC 7263 */ #include "config.h" @@ -2967,10 +2967,10 @@ static int dissect_diagnosticrequest(int anchor, tvbuff_t *tvb, packet_info *pin ti_local = proto_tree_add_item(tree, hf, tvb, offset, length, ENC_NA); local_tree = proto_item_add_subtree(ti_local, ett_reload_diagnosticrequest); - proto_tree_add_item(local_tree, hf_reload_diagnostic_expiration, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + proto_tree_add_item(local_tree, hf_reload_diagnostic_expiration, tvb, offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(local_tree, hf_reload_diagnosticrequest_timestampinitiated, tvb, - offset+local_offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + offset+local_offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN); local_offset += 8; local_offset += dissect_dmflag(tvb, local_tree, offset+local_offset); local_length = tvb_get_ntohl(tvb, offset+local_offset); @@ -3202,10 +3202,10 @@ static int dissect_diagnosticresponse(int anchor, tvbuff_t *tvb, packet_info *pi ti_local = proto_tree_add_item(tree, hf, tvb, offset, length, ENC_NA); local_tree = proto_item_add_subtree(ti_local, ett_reload_diagnosticresponse); - proto_tree_add_item(local_tree, hf_reload_diagnostic_expiration, tvb, offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + proto_tree_add_item(local_tree, hf_reload_diagnostic_expiration, tvb, offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(local_tree, hf_reload_diagnosticresponse_timestampreceived, - tvb, offset+local_offset, 8, ENC_TIME_NTP|ENC_BIG_ENDIAN); + tvb, offset+local_offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN); local_offset += 8; proto_tree_add_item(local_tree, hf_reload_diagnosticresponse_hopcounter, tvb, offset+local_offset, 1, ENC_BIG_ENDIAN); diff --git a/epan/dissectors/packet-synphasor.c b/epan/dissectors/packet-synphasor.c index fd43a98a2c..9aba75ac31 100644 --- a/epan/dissectors/packet-synphasor.c +++ b/epan/dissectors/packet-synphasor.c @@ -635,7 +635,7 @@ static gint dissect_header(tvbuff_t *tvb, proto_tree *tree) offset += 2; /* SOC */ - proto_tree_add_item(tree, hf_soc, tvb, offset, 4, ENC_TIME_TIMESPEC | ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_soc, tvb, offset, 4, ENC_TIME_SECS | ENC_BIG_ENDIAN); offset += 4; /* FRACSEC */ diff --git a/epan/proto.c b/epan/proto.c index f5a779dcbf..bf223d4456 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -1680,37 +1680,40 @@ get_stringzpad_value(wmem_allocator_t *scope, tvbuff_t *tvb, gint start, return tvb_get_string_enc(scope, tvb, start, length, encoding); } -/* this can be called when there is no tree, so don't add that as a param */ +/* + * Epochs for various non-UN*X time stamp formats. + */ +#define NTP_BASETIME G_GUINT64_CONSTANT(2208988800) /* NTP */ +#define TOD_BASETIME G_GUINT64_CONSTANT(2208988800) /* System/3x0 and z/Architecture TOD clock */ + +/* this can be called when there is no tree, so tree may be null */ static void -get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint encoding, - nstime_t *time_stamp, const gboolean is_relative) +get_time_value(proto_tree *tree, tvbuff_t *tvb, const gint start, + const gint length, const guint encoding, nstime_t *time_stamp, + const gboolean is_relative) { guint32 tmpsecs; guint64 todsecs; - /* relative timestamps don't do TOD/NTP */ - if (is_relative && - (encoding != (ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN)) && - (encoding != (ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN)) ) - { - /* XXX: I think this should call REPORT_DISSECTOR_BUG(), but - the existing code didn't do that, so I'm not either */ - return; - } - switch (encoding) { case ENC_TIME_TIMESPEC|ENC_BIG_ENDIAN: /* - * 4-byte UNIX epoch, possibly followed by - * 4-byte fractional time in nanoseconds, - * both big-endian. + * 4-byte seconds, followed by 4-byte fractional + * time in nanoseconds, both big-endian. + * For absolute times, the seconds are seconds + * since the UN*X epoch. */ time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start); if (length == 8) time_stamp->nsecs = tvb_get_ntohl(tvb, start+4); - else + else if (length == 4) { + /* + * Backwards compatibility. + */ time_stamp->nsecs = 0; + } else + report_type_length_mismatch(tree, "a timespec", length, TRUE); break; case ENC_TIME_TIMESPEC|ENC_LITTLE_ENDIAN: @@ -1718,21 +1721,27 @@ get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint e * 4-byte UNIX epoch, possibly followed by * 4-byte fractional time in nanoseconds, * both little-endian. + * For absolute times, the seconds are seconds + * since the UN*X epoch. */ time_stamp->secs = (time_t)tvb_get_letohl(tvb, start); if (length == 8) time_stamp->nsecs = tvb_get_letohl(tvb, start+4); - else + else if (length == 4) { + /* + * Backwards compatibility. + */ time_stamp->nsecs = 0; + } else + report_type_length_mismatch(tree, "a timespec", length, TRUE); break; case ENC_TIME_NTP|ENC_BIG_ENDIAN: /* * NTP time stamp, big-endian. + * Only supported for absolute times. */ - -/* XXX - where should this go? */ -#define NTP_BASETIME G_GUINT64_CONSTANT(2208988800) + DISSECTOR_ASSERT(!is_relative); /* We need a temporary variable here so the unsigned math * works correctly (for years > 2036 according to RFC 2030 @@ -1746,22 +1755,25 @@ get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint e if (length == 8) { /* - * We're using nanoseconds here (and we will - * display nanoseconds), but NTP's timestamps - * have a precision in microseconds or greater. - * Round to 1 microsecond. + * Convert 1/2^32s of a second to nanoseconds. + */ + time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0)); + } else if (length == 4) { + /* + * Backwards compatibility. */ - time_stamp->nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0)); - time_stamp->nsecs *= 1000; - } else { time_stamp->nsecs = 0; - } + } else + report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE); break; case ENC_TIME_NTP|ENC_LITTLE_ENDIAN: /* - * NTP time stamp, big-endian. + * NTP time stamp, little-endian. + * Only supported for absolute times. */ + DISSECTOR_ASSERT(!is_relative); + tmpsecs = tvb_get_letohl(tvb, start); if (tmpsecs) time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME); @@ -1770,37 +1782,49 @@ get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint e if (length == 8) { /* - * We're using nanoseconds here (and we will - * display nanoseconds), but NTP's timestamps - * have a precision in microseconds or greater. - * Round to 1 microsecond. + * Convert 1/2^32s of a second to nanoseconds. + */ + time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0)); + } else if (length == 4) { + /* + * Backwards compatibility. */ - time_stamp->nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0)); - time_stamp->nsecs *= 1000; - } else { time_stamp->nsecs = 0; - } + } else + report_type_length_mismatch(tree, "an NTP time stamp", length, TRUE); break; case ENC_TIME_TOD|ENC_BIG_ENDIAN: /* - * TOD time stamp, big-endian. + * S/3x0 and z/Architecture TOD clock time stamp, + * big-endian. + * Only supported for absolute times. */ -/* XXX - where should this go? */ -#define TOD_BASETIME G_GUINT64_CONSTANT(2208988800) + DISSECTOR_ASSERT(!is_relative); + DISSECTOR_ASSERT(length == 8); - todsecs = tvb_get_ntoh64(tvb, start) >> 12; - time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME); - time_stamp->nsecs = (int)((todsecs % 1000000) * 1000); + if (length == 8) { + todsecs = tvb_get_ntoh64(tvb, start) >> 12; + time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME); + time_stamp->nsecs = (int)((todsecs % 1000000) * 1000); + } else + report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE); break; case ENC_TIME_TOD|ENC_LITTLE_ENDIAN: /* - * TOD time stamp, big-endian. + * S/3x0 and z/Architecture TOD clock time stamp, + * little-endian. + * Only supported for absolute times. */ - todsecs = tvb_get_letoh64(tvb, start) >> 12 ; - time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME); - time_stamp->nsecs = (int)((todsecs % 1000000) * 1000); + DISSECTOR_ASSERT(!is_relative); + + if (length == 8) { + todsecs = tvb_get_letoh64(tvb, start) >> 12 ; + time_stamp->secs = (time_t)((todsecs / 1000000) - TOD_BASETIME); + time_stamp->nsecs = (int)((todsecs % 1000000) * 1000); + } else + report_type_length_mismatch(tree, "a TOD clock time stamp", length, TRUE); break; case ENC_TIME_RTPS|ENC_BIG_ENDIAN: @@ -1809,20 +1833,19 @@ get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint e * as NTP, but with the origin of the time stamp being * the UNIX epoch rather than the NTP epoch; big- * endian. + * + * Only supported for absolute times. */ - time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start); + DISSECTOR_ASSERT(!is_relative); + if (length == 8) { + time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start); /* - * We're using nanoseconds here (and we will - * display nanoseconds), but NTP's timestamps - * have a precision in microseconds or greater. - * Round to 1 microsecond. + * Convert 1/2^32s of a second to nanoseconds. */ - time_stamp->nsecs = (int)(1000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0)); - time_stamp->nsecs *= 1000; - } else { - time_stamp->nsecs = 0; - } + time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohl(tvb, start+4)/4294967296.0)); + } else + report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE); break; case ENC_TIME_RTPS|ENC_LITTLE_ENDIAN: @@ -1831,38 +1854,183 @@ get_time_value(tvbuff_t *tvb, const gint start, const gint length, const guint e * as NTP, but with the origin of the time stamp being * the UNIX epoch rather than the NTP epoch; little- * endian. + * + * Only supported for absolute times. */ - time_stamp->secs = (time_t)tvb_get_letohl(tvb, start); + DISSECTOR_ASSERT(!is_relative); + if (length == 8) { + time_stamp->secs = (time_t)tvb_get_letohl(tvb, start); /* - * We're using nanoseconds here (and we will - * display nanoseconds), but NTP's timestamps - * have a precision in microseconds or greater. - * Round to 1 microsecond. + * Convert 1/2^32s of a second to nanoseconds. */ - time_stamp->nsecs = (int)(1000000*(tvb_get_letohl(tvb, start+4)/4294967296.0)); - time_stamp->nsecs *= 1000; - } else { - time_stamp->nsecs = 0; - } + time_stamp->nsecs = (int)(1000000000*(tvb_get_letohl(tvb, start+4)/4294967296.0)); + } else + report_type_length_mismatch(tree, "an RTPS time stamp", length, TRUE); break; case ENC_TIME_TIMEVAL|ENC_BIG_ENDIAN: /* - * 4-byte UNIX epoch, followed by 4-byte fractional + * 4-byte seconds, followed by 4-byte fractional * time in microseconds, both big-endian. + * For absolute times, the seconds are seconds + * since the UN*X epoch. */ - time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start); - time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000; + if (length == 8) { + time_stamp->secs = (time_t)tvb_get_ntohl(tvb, start); + time_stamp->nsecs = tvb_get_ntohl(tvb, start+4)*1000; + } else + report_type_length_mismatch(tree, "a timeval", length, TRUE); break; case ENC_TIME_TIMEVAL|ENC_LITTLE_ENDIAN: /* - * 4-byte UNIX epoch, followed by 4-byte fractional + * 4-byte seconds, followed by 4-byte fractional * time in microseconds, both little-endian. + * For absolute times, the seconds are seconds + * since the UN*X epoch. */ - time_stamp->secs = (time_t)tvb_get_letohl(tvb, start); - time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000; + if (length == 8) { + time_stamp->secs = (time_t)tvb_get_letohl(tvb, start); + time_stamp->nsecs = tvb_get_letohl(tvb, start+4)*1000; + } else + report_type_length_mismatch(tree, "a timeval", length, TRUE); + break; + + case ENC_TIME_SECS|ENC_BIG_ENDIAN: + case ENC_TIME_SECS|ENC_LITTLE_ENDIAN: + /* + * Seconds, 1 to 8 bytes. + * For absolute times, it's seconds since the + * UN*X epoch. + */ + if (length >= 1 && length <= 8) { + time_stamp->secs = (time_t)get_uint64_value(tree, tvb, start, length, encoding); + time_stamp->nsecs = 0; + } else + report_type_length_mismatch(tree, "a time-in-seconds time stamp", length, TRUE); + break; + + case ENC_TIME_MSECS|ENC_BIG_ENDIAN: + /* + * Milliseconds, 1 to 8 bytes. + * For absolute times, it's milliseconds since the + * UN*X epoch. + */ + if (length >= 1 && length <= 8) { + guint64 msecs; + + msecs = get_uint64_value(tree, tvb, start, length, encoding); + time_stamp->secs = (time_t)(msecs / 1000); + time_stamp->nsecs = (int)(msecs % 1000); + } else + report_type_length_mismatch(tree, "a time-in-milliseconds time stamp", length, TRUE); + break; + + case ENC_TIME_RFC_3971|ENC_BIG_ENDIAN: + /* + * 1/64ths of a second since the UN*X epoch, + * big-endian. + * + * Only supported for absolute times. + */ + DISSECTOR_ASSERT(!is_relative); + + if (length == 8) { + /* + * The upper 48 bits are seconds since the + * UN*X epoch. + */ + time_stamp->secs = tvb_get_ntoh48(tvb, start); + /* + * The lower 16 bits are 1/2^16s of a second; + * convert them to nanoseconds. + * + * XXX - this may give the impression of higher + * precision than you actually get. + */ + time_stamp->nsecs = (int)(1000000000*(tvb_get_ntohs(tvb, start+6)/65536.0)); + } else + report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE); + break; + + case ENC_TIME_RFC_3971|ENC_LITTLE_ENDIAN: + /* + * 1/64ths of a second since the UN*X epoch, + * little-endian. + * + * Only supported for absolute times. + */ + DISSECTOR_ASSERT(!is_relative); + + if (length == 8) { + /* + * XXX - this is assuming that, if anybody + * were ever to use this format - RFC 3971 + * doesn't, because that's an Internet + * protocol, and those use network byte + * order, i.e. big-endian - they'd treat it + * as a 64-bit count of 1/2^16s of a second, + * putting the upper 48 bits at the end. + * + * The lower 48 bits are seconds since the + * UN*X epoch. + */ + time_stamp->secs = tvb_get_letoh48(tvb, start+2); + /* + * The upper 16 bits are 1/2^16s of a second; + * convert them to nanoseconds. + * + * XXX - this may give the impression of higher + * precision than you actually get. + */ + time_stamp->nsecs = (int)(1000000000*(tvb_get_letohs(tvb, start)/65536.0)); + } else + report_type_length_mismatch(tree, "an RFC 3971-style time stamp", length, TRUE); + break; + + case ENC_TIME_SECS_NTP|ENC_BIG_ENDIAN: + /* + * NTP time stamp, with 1-second resolution (i.e., + * seconds since the NTP epoch), big-endian. + * Only supported for absolute times. + */ + DISSECTOR_ASSERT(!is_relative); + + if (length == 4) { + /* + * We need a temporary variable here so the + * unsigned math works correctly (for + * years > 2036 according to RFC 2030 + * chapter 3). + */ + tmpsecs = tvb_get_ntohl(tvb, start); + if (tmpsecs) + time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME); + else + time_stamp->secs = tmpsecs; /* 0 */ + time_stamp->nsecs = 0; + } else + report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE); + break; + + case ENC_TIME_SECS_NTP|ENC_LITTLE_ENDIAN: + /* + * NTP time stamp, with 1-second resolution (i.e., + * seconds since the NTP epoch), little-endian. + * Only supported for absolute times. + */ + DISSECTOR_ASSERT(!is_relative); + + if (length == 4) { + tmpsecs = tvb_get_letohl(tvb, start); + if (tmpsecs) + time_stamp->secs = (time_t)(tmpsecs - (guint32)NTP_BASETIME); + else + time_stamp->secs = tmpsecs; /* 0 */ + time_stamp->nsecs = 0; + } else + report_type_length_mismatch(tree, "an NTP seconds-only time stamp", length, TRUE); break; default: @@ -2278,7 +2446,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, report_type_length_mismatch(tree, "an absolute time value", length, length_error); } - get_time_value(tvb, start, length, encoding, &time_stamp, FALSE); + get_time_value(tree, tvb, start, length, encoding, &time_stamp, FALSE); proto_tree_set_time(new_fi, &time_stamp); break; @@ -2305,7 +2473,7 @@ proto_tree_new_item(field_info *new_fi, proto_tree *tree, report_type_length_mismatch(tree, "a relative time value", length, length_error); } - get_time_value(tvb, start, length, encoding, &time_stamp, TRUE); + get_time_value(tree, tvb, start, length, encoding, &time_stamp, TRUE); proto_tree_set_time(new_fi, &time_stamp); break; @@ -2846,7 +3014,7 @@ proto_tree_add_time_item(proto_tree *tree, int hfindex, tvbuff_t *tvb, } tvb_ensure_bytes_exist(tvb, start, length); - get_time_value(tvb, start, length, encoding, &time_stamp, is_relative); + get_time_value(tree, tvb, start, length, encoding, &time_stamp, is_relative); if (endoff) *endoff = length; } diff --git a/epan/proto.h b/epan/proto.h index bf0ae5e2c9..1ddf718bec 100644 --- a/epan/proto.h +++ b/epan/proto.h @@ -371,32 +371,43 @@ WS_DLL_PUBLIC WS_NORETURN void proto_report_dissector_bug(const char *message); * * We now support: * - * ENC_TIME_TIMESPEC - 4 or 8 bytes; the first 4 bytes are seconds since - * the UN*X epoch (1970-01-01 00:00:00 UTC), and, if there are 8 bytes, - * the next 4 bytes are nanoseconds since that second. (I.e., a UN*X - * struct timespec with a 4-byte time_t.) + * ENC_TIME_TIMESPEC - 8 bytes; the first 4 bytes are seconds and the + * next 4 bytes are nanoseconds. If the time is absolute, the seconds + * are seconds since the UN*X epoch (1970-01-01 00:00:00 UTC). (I.e., + * a UN*X struct timespec with a 4-byte time_t.) * - * ENC_TIME_NTP - 4 or 8 bytes; the first 4 bytes are seconds since - * the NTP epoch (1901-01-01 00:00:00 GMT), and, if there are 8 bytes, - * the next 4 bytes are 1/2^32's of a second since that second. (I.e., - * a 64-bit count of 1/2^32's of a second since the NTP epoch, with - * the upper 32 bits first and the lower 32 bits second, even when - * little-endian.) + * ENC_TIME_NTP - 8 bytes; the first 4 bytes are seconds since the NTP + * epoch (1901-01-01 00:00:00 GMT) and the next 4 bytes are 1/2^32's of + * a second since that second. (I.e., a 64-bit count of 1/2^32's of a + * second since the NTP epoch, with the upper 32 bits first and the + * lower 32 bits second, even when little-endian.) * * ENC_TIME_TOD - 8 bytes, as a count of microseconds since the System/3x0 * and z/Architecture epoch (1900-01-01 00:00:00 GMT). * - * ENC_TIME_RTPS - 4 or 8 bytes; the first 4 bytes are seconds since the - * UN*X epoch, and, if there are 8 bytes, the next 4 bytes are are - * 1/2^32's of a second since that second. (I.e., it's the offspring - * of a mating between UN*X time and NTP time.) It's used by the Object - * Management Group's Real-Time Publish-Subscribe Wire Protocol for the - * Data Distribution Service. + * ENC_TIME_RTPS - 8 bytes; the first 4 bytes are seconds since the UN*X + * epoch and the next 4 bytes are are 1/2^32's of a second since that + * second. (I.e., it's the offspring of a mating between UN*X time and + * NTP time.) It's used by the Object Management Group's Real-Time + * Publish-Subscribe Wire Protocol for the Data Distribution Service. * - * ENC_TIME_TIMEVAL - 8 bytes; the first 4 bytes are seconds since - * the UN*X epoch (1970-01-01 00:00:00 UTC), and, if there are 8 bytes, - * the next 4 bytes are microseconds since that second. (I.e., a UN*X - * struct timeval with a 4-byte time_t.) + * ENC_TIME_TIMEVAL - 8 bytes; the first 4 bytes are seconds and the + * next 4 bytes are microseconds. If the time is absolute, the seconds + * are seconds since the UN*X epoch. (I.e., a UN*X struct timeval with + * a 4-byte time_t.) + * + * ENC_TIME_SECS - 4 to 8 bytes, representing a value in seconds. + * If the time is absolute, it's seconds since the UN*X epoch. + * + * ENC_TIME_MSECS - 6 to 8 bytes, representing a value in milliseconds. + * If the time is absolute, it's milliseconds since the UN*X epoch. + * + * ENC_TIME_SECS_NTP - 4 bytes, representing a count of seconds since + * the NTP epoch. (I.e., seconds since the NTP epoch.) + * + * ENC_TIME_RFC_3971 - 8 bytes, representing a count of 1/64ths of a + * second since the UN*X epoch; see section 5.3.1 "Timestamp Option" + * in RFC 3971. */ #define ENC_TIME_TIMESPEC 0x00000000 #define ENC_TIME_NTP 0x00000002 @@ -404,6 +415,10 @@ WS_DLL_PUBLIC WS_NORETURN void proto_report_dissector_bug(const char *message); #define ENC_TIME_RTPS 0x00000008 #define ENC_TIME_NTP_BASE_ZERO ENC_TIME_RTP /* for backwards source compatibility */ #define ENC_TIME_TIMEVAL 0x00000010 +#define ENC_TIME_SECS 0x00000012 +#define ENC_TIME_MSECS 0x00000014 +#define ENC_TIME_SECS_NTP 0x00000018 +#define ENC_TIME_RFC_3971 0x00000020 /* * Historically, the only place the representation mattered for strings