Search code examples
wiresharkwireshark-dissector

Wireshark dissector: format epoch time


I'm writing a Wireshark dissector (the C variety, not Lua).

I have time fields which are uint64, representing the nanoseconds since the unix epoch.

I'd like to print the time in a human-readable format in wireshark.

I looked around for documentation to show how to do this, and only found this time-related function proto_tree_add_time, at https://anonsvn.wireshark.org/wireshark/trunk-1.6/doc/README.developer.

I end up writing a helper function like this:

static void add_pretty_time(tvbuff_t* tvb, proto_tree* body, unsigned field_offset, int field_id)
{
    uint64_t raw_time = tvb_get_letoh64(tvb, field_offset);
    nstime_t time;
    time.secs = raw_time / 1000000000;
    time.nsecs = raw_time % 1000000000;
    proto_tree_add_time(body, field_id, tvb, field_offset, 8, &time);
}

Is there any more-elegant way provided by Wireshark to do this? For example FT_UINT64, BASE_DEC in the hf_register_info array can specify that this field should be parsed as a uint64 and displayed in decimal format. It would be ideal if there was something like FT_EPOCH64, ISO_FORMAT at the hf_register_info array.


Solution

  • 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 found at: https://github.com/wireshark/wireshark/blob/master/doc/README.dissector#L1648

    ENC_TIME_SECS_NSECS - 8, 12, or 16 bytes.  For 8 bytes, the first 4
        bytes are seconds and the next 4 bytes are nanoseconds; for 12
        bytes, the first 8 bytes are seconds and the next 4 bytes are
        nanoseconds; for 16 bytes, the first 8 bytes are seconds and
        the next 8 bytes are nanoseconds.  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 or 8-byte time_t or a structure
        with an 8-byte time_t and an 8-byte nanoseconds field.)
    
    ENC_TIME_NTP - 8 bytes; the first 4 bytes are seconds since the NTP
        epoch (1900-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_SECS_USECS - 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_MSEC_NTP - 4-8 bytes, representing a count of milliseconds since
        the NTP epoch.  (I.e., milliseconds since the NTP epoch.)
    

    None of them correspond to uint64 nanoseconds past epoch.

    The add_pretty_time helper written in the question is the right approach, since we are forced to use proto_tree_add_time instead of using the standard proto_tree_add_item with the help of built-in encodings.

    This still requires that the hf_register_info array has the correct values: i.e. we must use a time-based field type, and a time-based display format. Example of the former: FT_ABSOLUTE_TIME. Example of the latter: ABSOLUTE_TIME_UTC. Where to find a list of each: https://github.com/boundary/wireshark/blob/master/epan/proto.c#L4742 and https://github.com/wireshark/wireshark/blob/master/doc/README.dissector#L147 respectively.