Wireshark-dev: Re: [Wireshark-dev] getting the time
From: Brian Oleksa <oleksab@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 21 Jan 2010 14:59:01 -0500
Guy

I am not sure I follow you. Basically all I do is count packets based on what I know is in the packet.

Here is the whole packet that I am dissecting: (See below)

So when I get to Time.. I check for
if ((fieldsAvail & 2) != 0)
Then I look at the pointer (which will point me to the right set of bytes).

But how I start the initial counting process is I do the following:

guint8 * ptr = (guint8*) tvb->real_data;

Actually..... maybe you can see your answer better in the code. I have attached the packet-helen.c file.

Any help on how I can get and format the time is greatly appreciated.

Thanks,
Brian



Field 	Size 	Notes 	Meaning
Fields Available 1 Each bit of this byte indicates that a particular field is available in this message. See table below.
Status 	1/0 	  	GPS status. 0 = Good, 1 = No Fix, 2 = Bad GPS Read
Time 8/0 GPS Time of the transmitting system. This may be different than the system time.
Longitude 	4/0 	  	Longitude in decimal degrees (float)
Latitude 	4/0 	  	Latitude in decimal degrees (float)
Altitude 	4/0 	  	Altitude in decimal meters (float)
Bearing 	4/0 	  	Bearing in decimal degrees from north (float)
Speed 	4/0 	  	Speed in decimal m/s (float)
Number of Satellites 	1/0 	  	Number of satellites current fix is based on

*Note:* Check *Fields Available* to determine if each field is present. For floating point fields, the floating point number is written in network byte order as if it were a four byte integer.

Bit Mask 	Field Referenced
1 	Status
2 	Time
4 	Longitude
8 	Latitude
16 	Altitude
32 	Bearing
64 	Speed
128 	Number of Satellites



Guy Harris wrote:
On Jan 21, 2010, at 11:25 AM, Brian Oleksa wrote:

It is a pointer into the data that I have constructed based on the data in the packet.

So what do you have to do to the raw data in the packet to construct that buffer?
___________________________________________________________________________
Sent via:    Wireshark-dev mailing list <wireshark-dev@xxxxxxxxxxxxx>
Archives:    http://www.wireshark.org/lists/wireshark-dev
Unsubscribe: https://wireshark.org/mailman/options/wireshark-dev
             mailto:wireshark-dev-request@xxxxxxxxxxxxx?subject=unsubscribe
/* packet-helen.c
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <glib.h>
#include <epan/packet.h>
#include <time.h>
#include <string.h>

#define PROTO_TAG_HELEN    "HELEN"

static int proto_helen = -1;

static dissector_handle_t data_handle = NULL;

static dissector_handle_t helen_handle;

void dissect_helen(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);

static int helen_port = 7636;

static const value_string packettypenames[] = {
    { 0, "TEXT"},
    { 1, "SOMETHING_ELSE"},
    { 0, NULL}
};

static gint hf_helen = -1;
static gint hf_helen_length = -1;
static gint hf_helen_type = -1;
static gint hf_helen_text = -1;

static gint ett_helen = -1;
static gint ett_helen_header = -1;
static gint ett_helen_length = -1;
static gint ett_helen_type = -1;
static gint ett_helen_text = -1;

void proto_reg_handoff_helen(void) {
    static gboolean initialized = FALSE;

        if (!initialized) {
            data_handle = find_dissector("data");
            helen_handle = create_dissector_handle(dissect_helen, proto_helen);
            dissector_add("udp.port", helen_port, helen_handle);
        }
    initialized = TRUE;
}

void proto_register_helen(void) {
    static hf_register_info hf[] = {
        { &hf_helen,
            { "Data", "helen.data", FT_NONE, BASE_NONE, NULL, 0x0,
                "HELEN PDU", HFILL}},
        { &hf_helen_length,
            { "Package Length2", "helen.len", FT_UINT32, BASE_DEC, NULL, 0x0,
                "Package Length3", HFILL}},
        { &hf_helen_type,
            { "Type", "helen.type", FT_UINT8, BASE_DEC, VALS(packettypenames), 0x0,
                "Package Type", HFILL}},
        { &hf_helen_text,
            { "Text", "helen.text", FT_STRING, BASE_NONE, NULL, 0x0,
                "Text", HFILL}}
    };
    static gint * ett[] = {
        &ett_helen,
        &ett_helen_header,
        &ett_helen_length,
        &ett_helen_type,
        &ett_helen_text,
    };

    proto_helen = proto_register_protocol("HELEN", "HELEN", "helen");
    proto_register_field_array(proto_helen, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));
    register_dissector("helen", dissect_helen, proto_helen);
}


static const value_string helen_vals[] = {
    {1, "GPS"},
    {2, "Flow"},
    {3, "Host"},
    {1000, "Minotaur SA Extension"},
    {0, NULL}
};

guint16 swap16(guint16 in) {
    guint8 high = (in >> 8) & 0xff;
    guint8 low = in & 0xff;
    guint16 newVal = (low << 8) | high;
    return newVal;
}

guint32 swap32(guint32 in) {
    guint8 b1 = (in >> 24) & 0xff;
    guint8 b2 = (in >> 16) & 0xff;
    guint8 b3 = (in >> 8) & 0xff;
    guint8 b4 = in & 0xff;
    guint32 newVal = (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
    return newVal;
}

void dissect_helen(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

    proto_item *helen_item = NULL;
    proto_item *helen_sub_item = NULL;
    proto_tree *helen_tree = NULL;
    proto_tree *helen_header_tree = NULL;
    guint16 type = 0;

    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
        col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_HELEN);
    }

    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_clear(pinfo->cinfo, COL_INFO);
    }

    type = tvb_get_guint8(tvb, 4);

    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d Info Type:[%s]",
                pinfo->srcport, pinfo->destport,
                val_to_str(type, packettypenames, "Unknown Type:0x%02x"));
    }

    if (tree) {
        guint32 offset = 0;
        helen_item = proto_tree_add_item(tree, proto_helen, tvb, 0, -1, FALSE);
        helen_tree = proto_item_add_subtree(helen_item, ett_helen);
        helen_header_tree = proto_item_add_subtree(helen_item, ett_helen);
        helen_header_tree = proto_item_add_subtree(helen_sub_item, ett_helen);
        {
            guint8 * ptr = (guint8*) tvb->real_data;
            guint8 * packet_header = ptr;
            guint16 bead;
            char buf[100];
            char * packet_name = "";
            proto_tree *helen_sub_tree = NULL;
            guint swap = 0;

            bead = *((guint16*) packet_header);
            if (bead != 0xBEAD) {
                swap = 1;
            }

            offset += 18;
            ptr += 18; /* Skip the header.*/
            packet_header = ptr;

            for (;;) {
                guint16 code = *((guint16*) packet_header);
                guint16 numBytes = 0;
                guint unknownPacket = 0;
                guint codeOffset;
                ptr = packet_header;
                offset = (ptr - tvb->real_data);
                codeOffset = offset;

                if (swap) {
                    code = swap16(code);
                }

                ptr += 2;
                offset += 2;
                numBytes = *((guint16*) ptr);
                if (swap) {
                    numBytes = swap16(numBytes);
                }

                ptr += 2;
                offset += 2;

                switch (code) {
                    case 0: packet_name = "End of Packet";
                        break;
                    case 1: packet_name = "GPS Extension";
                        break;
                    case 2: packet_name = "Flow Extension";
                        break;
                    case 3: packet_name = "Host Extension";
                        break;
                    case 1000: packet_name = "Minotaur SA";
                        break;
                    default: packet_name = "Unknown code";
                        unknownPacket = 1;
                        break;
                }
                strcpy(buf, " ");
                strcat(buf, packet_name);
                if (unknownPacket) {
                    sprintf(buf, "Unknown packet: %d", code);
                }
                helen_item = proto_tree_add_text(tree, tvb, codeOffset, 2, "%s", buf);
                helen_sub_tree = proto_item_add_subtree(helen_item, ett_helen);

                if (code == 0) {
                    break;
                }

                // GPS:
                if (code == 1) {
                    guint8 fieldsAvail;
                    fieldsAvail = *((guint8*) ptr);
                    ptr += 1;
                    offset += 1;

                    // Status:
                    if ((fieldsAvail & 1) != 0) {
                        guint8 status;
                        char * statusStr = "";
                        status = *((guint8*) ptr);
                        if (status == 0) {
                            statusStr = "Good";
                        } else if (status == 1) {
                            statusStr = "No Fix";
                        } else if (status == 2) {
                            statusStr = "Bad GPS Read";
                        }
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "%s", statusStr);
                        ptr += 1;
                        offset += 1;
                    }

                    // Time:
					//Need to find a way to get and format the time.
                    if ((fieldsAvail & 2) != 0) {
                        ptr += 8;
                        offset += 8;
                    }


                    // Longitude:
                    if ((fieldsAvail & 4) != 0) {
                        gfloat longitude;
                        longitude = *((gfloat*) ptr);
                        if (swap) {
                            guint32 temp = *((guint32*) ptr);
                            temp = swap32(temp);
                            longitude = *((gfloat*) & temp);
                        }
                        ptr += 4;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Longitude: %f", longitude);
                        offset += 4;
                    }

                    // Latitude:
                    if ((fieldsAvail & 8) != 0) {
                        gfloat latitude;
                        latitude = *((gfloat*) ptr);
                        if (swap) {
                            guint32 temp = *((guint32*) ptr);
                            temp = swap32(temp);
                            latitude = *((gfloat*) & temp);
                        }
                        ptr += 4;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Latitude: %f", latitude);
                        offset += 4;
                    }

                    // Altitude:
                    if ((fieldsAvail & 16) != 0) {
                        gfloat altitude;
                        altitude = *((gfloat*) ptr);
                        if (swap) {
                            guint32 temp = *((guint32*) ptr);
                            temp = swap32(temp);
                            altitude = *((gfloat*) & temp);
                        }
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Altitude: %f", altitude);
                        offset += 4;
                    }

                    // Bearing:
                    if ((fieldsAvail & 32) != 0) {
                        gfloat bearing;
                        bearing = *((gfloat*) ptr);
                        if (swap) {
                            guint32 temp = *((guint32*) ptr);
                            temp = swap32(temp);
                            bearing = *((gfloat*) & temp);
                        }
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Bearing: %f", bearing);
                        offset += 4;
                    }

                    // Speed:
                    if ((fieldsAvail & 64) != 0) {
                        gfloat speed;
                        speed = *((gfloat*) ptr);
                        if (swap) {
                            guint32 temp = *((guint32*) ptr);
                            temp = swap32(temp);
                            speed = *((gfloat*) & temp);
                        }
                        ptr += 4;
                        if (speed != 0.0) {
                            proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                    "Speed: %f", speed);
                        }
                        offset += 4;
                    }

                    // Number of Satellites:
                    if ((fieldsAvail & 128) != 0) {
                        guint8 nos;
                        nos = *((guint8*) ptr);
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Number of Satellites: %d", nos);
                        ptr += 1;
                        offset += 1;
                    }

                }

                // FLOW:
                if (code == 2) {
                    char flowname[9];
                    guint32 seq;

                    strncpy(flowname, ptr, 8);
                    flowname[8] = '\0';
                    ptr += 8;
                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                            "Flowname: %s", flowname);
                    offset += 8;

                    // Sequence number:
                    seq = *((guint32*) ptr);
                    if (swap) {
                        seq = swap32(seq);
                    }
                    ptr += 4;
                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Sequence #: %d", seq);
                    offset += 4;
                }

                // HOST:
                if (code == 3) {
                    guint8 size;

                    // Size:
                    size = *((guint8*) ptr);
                    ptr += 1;
                    offset += 1;

                    if (size == 4) {
                        guint32 addr;

                        addr = *((guint32*) ptr);
                        if (swap) {
                            addr = swap32(addr);
                        }
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Address: %d.%d.%d.%d", addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff);
                        offset += 4;
                    }
			  }

                    //Minotaur SA Ext:
					  if (code == 1000) {
					   guint32 id;
					   id = *((guint32*) ptr);
					   if (swap) {
					     id = swap32(id);
					  }
					  ptr += 4;
					  proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
					      "Harmonice ID #: %d", id);
					  offset += 4;
                }

                packet_header += numBytes + 4;
            }
        }
        offset += 4;
        offset += 1;
    }
}