Wireshark-dev: Re: [Wireshark-dev] time question

From: Guy Harris <guy@xxxxxxxxxxxx>
Date: Thu, 8 Apr 2010 18:46:55 -0700
On Apr 8, 2010, at 7:41 AM, Brian Oleksa wrote:

> 
> Wiresharkers
> 
> I am trying to dissect the time in a particular packet. Here is it's format:

Sounds like

	https://www.darkcornersoftware.com/confluence/display/open/MGEN

or

	http://pf.itd.nrl.navy.mil/mgen/mgen.html

(please cite URLs for these protocols; that makes it a lot easier to discuss dissecting them).

> "The time is the source computer's system time in Greenwich Mean Time 
> (GMT)." The size is 32 bits or 4 bytes.

The time is a combination of txTimeSeconds and txTimeMicroseconds; the documentation (both the Dark Corner Software and Naval Research Lab version) just says "The <txTimeSeconds> and <txTimeMicroseconds> fields are used to mark the time of transmission of the MGEN message. The time is the source computer's system time in Greenwich Mean Time (GMT)", but given that the software runs on UN*X (as well as Windows), and that it's seconds and microseconds, I strongly suspect that what they mean is that txTimeSeconds is seconds since the UN*X epoch.

Given that, the best way to dissect it is:

	nstime_t t;

	t.secs = tvb_get_ntohl(tvb, offset);		/* txTimeSeconds */
	t.nsecs = tvb_get_ntohl(tvb, offset + 4)*1000;	/* txTimeMicroseconds */
	tmp = gmtime(&t.secs)
	if (tmp != NULL) {
		proto_tree_add_time_format(time_sub_tree, hf_mgen_time, tvb, offset, 8, &t,
		    "Date: %s %2d, %d %02d:%02d:%02d.%09ld UTC", mon_names[tmp->tm_mon], tmp->tm_mday,
		    tmp->tm_year + 1900, tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
		    (long)t.nsecs);
	}
	offset += 8;

although that could give the impression that the time has nanosecond precision, with the sub-second time displayed with 9 digits.  To make the microsecond precision a little clearer:

	time_t tsecs;
	guint32 tmicrosecs;

	tsecs = tvb_get_ntohl(tvb, offset);		/* txTimeSeconds */
	tmicrosecs = tvb_get_ntohl(tvb, offset + 4);	/* txTimeMicroseconds */
	tmp = gmtime(&tsecs)
	if (tmp != NULL) {
		proto_tree_add_time_format(time_sub_tree, hf_mgen_time, tvb, offset, 8, &t,
		    "Date: %s %2d, %d %02d:%02d:%02d.%06d UTC", mon_names[tmp->tm_mon], tmp->tm_mday,
		    tmp->tm_year + 1900, tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
		    tmicrosecs);
	}
	offset += 8;

(I'm using hf_mgen_time rather than hf_helen_time because I'm assuming this is a dissector for MGEN, not for Helen).

> Also...I am trying to dissect longitude, latitude and altitude. Here is 
> it's format. The size is also 32 bits or 4 bytes.
> 
> The <latitude>, <longitude>, and <altitude> fields contain values 
> corresponding to GPS information for the MGEN source if it was 
> available. The <latitude> and <longitude> fields are encoded as follows:
> 
> <fieldValue> = (unsigned long)((<actualValue>+180.0)*60000.0)

Presumably that means that the 32-bit quantity in the packet is the actual latitude or longitude, plus 180 (presumably the latitude and longitude are in degrees from the equator or prime meridian, hence between -180 and +180), times 60000 (presumably because the <actualValue> includes fractions of a degree).

Therefore, to convert the value in the packet to the actual degrees-plus-fraction of longitude or latitude, it's

	<actualValue> = (<fieldValue>/60000.0) - 180.0

> The <altitude> field is the direct representation of the altitude value 
> available from the source's GPS system.
> 
> I tried this but had no luck:
> 
>            longitude = tvb_get_ntoh64(tvb, offset);

If it's 32 bits, you don't want tvb_get_ntoh64() - the "64" in "tvb_get_ntoh64" means it's for 64-bit quantities.

>            longitude = (longitude+180)*60000;

That's backwards.  That would be correct (modulo using floating-point) to convert an *actual* value to a *field* value, but you want to convert the *field* value (that being what you get from the packet) to an *actual* value.
 
>            proto_tree_add_uint_format(mgen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
>                  "Longitude: %f", longitude);

That's setting the value of the field to 0.

Try:

	guint32 field_longitude;
	double actual_longitude;

	field_longitude = tvb_get_ntohl(tvb, offset);
	actual_longitude = (field_longitude/60000.0) - 180.0;
	proto_tree_add_uint_format(mgen_sub_tree, hf_mgen_longitude, tvb, offset, 4, field_longitude,
	    "Longitude: %f degrees (%u)", actual_longitude, field_longitude);
	offset += 4;

(the "(%u)" at the end shows the raw field value, in case somebody wants to see that; this is by analogy to fields with value_string tables, so that you show the interpreted value, followed by the raw value in parentheses - we should perhaps have built into Wireshark the ability to do at least some form of linear transformation of raw data to go from raw value to display value).