Wireshark-dev: Re: [Wireshark-dev] wireshark GUI vs tshark

From: Brian Oleksa <oleksab@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 24 Nov 2009 10:59:28 -0500
Jaap and Chris

I appreciate your help.
I apologize for the messy code....this is my development code.

I have changed some of the code based on your suggestions that you made below: Such as...

FT_BYTES, BASE_HEX is now FT_BYTES, BASE_NONE
I have closed off the value_string helen_vals[] with {0, NULL}

However.. I do have some questions.

What do you mean when you say:  "You forget to set initialized to TRUE in your handoff functions."

Also..why does accessing tvbuff this way pose a problem..??    guint8 * ptr = (guint8*) tvb->real_data;
Accessing tvbuff this way appears to be working fine...but would like some feed back if there is a well-known & correct way to do this.

I have attached a clean version of the code. It is now formatted and all the old commented out code is now removed.

I am a java programmer and just started to dig into this C stuff....So I apologize for any code that does not make sense.

Again...any help is greatly appreciated.

Thanks,
Brian



Jaap Keuter wrote:
Hi,

Oke, quick review then.

First of all the code is a mess. That results in:
1. hard to look through.
2. hard to spot even obvious errors.

You forget to set initialized to TRUE in your handoff functions.

  FT_BYTES, BASE_HEX should be FT_BYTES, BASE_NONE

Many inconsistencies in header blubs and labels.

value_string helen_vals[] isn't closed off by {0, NULL}

	        guint8 * ptr = (guint8*) tvb->real_data;
Going about this way of accessing tvbuff data leads guaranteed to failure.
For me it's enough to abort furher review of this code.

My advice: really read all of doc/README.developer and take the advice to hart.

Thanks,
Jaap

Brian Oleksa wrote:
Jaap

Eventually this might get licensed...but just not sure what direction we will be going.

I have tracked down many many problems before when my code crashed within the GUI...because I would get some what of a decent error. But I am having a hard time tracking down this bug as it runs fine in the GUI but not in tshark.

Doesn't tshark run off the same base code as the GUI does..?? If so...then you think if it would crash in one that it would crash in the other....wouldn't you think..??

Attached is my code. Any help is greatly appreciated.

Thank you
Brian





Jaap Keuter wrote:
Hi,

Well, your assumption is probably right, that your dissector has something to do with it.

You can post it, but we prefer to spend our time on GPL'ed code. I don't know what you license will be. If you prefer not to publish your code you can probably find enough clues in the documentation in the doc directory.

Thanks,
Jaap

Brian Oleksa wrote:
Chris and Jaap

Well.... I guess I can point out the obvious here:

I wrote a dissector that works fine with the GUI with no problem...but it crashes when I use tshark.

HOWEVER... if I remove my dissector....then my pcap file loads fine within tshark.

So the problem has to be with my dissector....correct..??

Is there anyway I can post my code so you can take a look..??

This is hard to track down as again everything works fine in the GUI and I get NO real error message within tshark.

What do you think..?

Thanks,
Brian



Maynard, Chris wrote:
The file may not be corrupt but might contain packet(s) which are
exposing a tshark bug.  If you can post the capture file, that would
probably help.  If you don't wish to post it on the mailing list, you
can open a bug report and post it there instead, marking the file as
private if you so desire so only the core developers have access to it.

- Chris

-----Original Message-----
From: wireshark-dev-bounces@xxxxxxxxxxxxx
[mailto:wireshark-dev-bounces@xxxxxxxxxxxxx] On Behalf Of Brian Oleksa
Sent: Monday, November 23, 2009 12:59 PM
To: Developer support list for Wireshark
Subject: Re: [Wireshark-dev] wireshark GUI vs tshark

Jaap and Chris

I am running this on Win XP service pack 2.
I am using wireshark Version 1.2.4 (SVN Rev 30978).

The test.pcap file has been around for a while...so chances are it is not corrupt. It never crashes using the GUI...it just crashes and gives me that pop up when I run it with that tshark command.

This is about all the information that I can provide....unless you can think of something else that you need..??

Thanks,
Brian


Jaap Keuter wrote:
Hi Brian,

Thanks for including the error report. It in itself doesn't tell
anything,
other than that a problem was detected. That's why Chris asked you
some
more questions on the whole situation. Maybe we can help you further
when
you look into them.

Thanks,
Jaap

On Mon, 23 Nov 2009 12:02:17 -0500, Brian Oleksa
<oleksab@xxxxxxxxxxxxxxxxxxxxxx> wrote:
Chris

I have attached the error this time....sorry about that. :-)

I get this error when I run with tshark using the following command:

tshark -nr test.pcap ip.dst==x.x.x.x
But when I filter in the GUI ... I have no problems.

Thanks,
Brian





Maynard, Chris wrote:
Any thoughts..??
My first thought was, "I guess you forgot to include the error." :)

In addition to the error, you might want to include some Wireshark
version information, what OS you're running on and any other
information
that you think might be relevant.

By the way, I tried a similar tshark command using Wireshark 1.2.4
on
Windows XP SP3 with no problems.  Maybe you are running an older
version
of Wireshark with a known bug that has been fixed, or maybe your
test.pcap file is corrupt or exposes a Wireshark bug, in which case
a
bug report might be in order with the attached test.pcap file
included
so the core developers can analyze the error and find & fix the bug.

- Chris

-----Original Message-----
From: wireshark-dev-bounces@xxxxxxxxxxxxx
[mailto:wireshark-dev-bounces@xxxxxxxxxxxxx] On Behalf Of Brian
Oleksa
Sent: Sunday, November 22, 2009 10:49 PM
To: Developer support list for Wireshark
Subject: [Wireshark-dev] wireshark GUI vs tshark


Wiresharkers

When I use my dissector with the GUI... everything works fine. The
pcap
file that I load comes right up with NO problems. I can filter (ip.dst==x.x.x.x) with no problems.

But if I try to open that same pcap file with tshark using the
following
command:

tshark -nr test.pcap ip.dst==x.x.x.x The files appears to start loading.. then I get the following error.

Any thoughts..??

Thanks,
Brian

___________________________________________________________________________
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 <epan/tvbuff.h>
#include <time.h>

#include <string.h>

#define PROTO_TAG_HELEN    "HELEN"

#define PROTO_TAG_NETALIVE    "NETALIVE"

/* Wireshark ID of the HELEN protocol */
static int proto_helen = -1;
static int proto_netalive = -1;


/* These are the handles of our subdissectors */
static dissector_handle_t data_handle = NULL;
static dissector_handle_t netalivedata_handle = NULL;

static dissector_handle_t helen_handle;

static dissector_handle_t netalive_handle;

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

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

static int ports[25] = {5000, 5220, 42250, 50000, 5221, 5222, 49901, 49501, 49510, 42251, 42250, 56797, 5226, 47001, 5227, 7636, 59201,
				59202, 59203, 59204, 59205, 59206, 59207, 59209, 59210};
static int global_netalive_port = 56797;

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

// Declarations:
int numBytesInMode(int numBits);
int numBytesInBitmask(int numBits);
char * translateWFMode(int val);


/* The following hf_* variables are used to hold the Wireshark IDs of
 * our header fields; they are filled out when we call
 * proto_register_field_array() in proto_register_helen()
 */
/** Kts attempt at defining the protocol */
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 hf_helen_Flowname = -1;

static gint hf_netalive = -1;
static gint hf_netalive_length = -1;
static gint hf_netalive_type = -1;
static gint hf_netalive_text = -1;

static gint hf_helen_magic = -1;
static gint hf_helen_checksum = -1;
static gint hf_helen_txTime = -1;

/* These are the ids of the subtrees that we may be creating */
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;
static gint ett_helen_Flowname = -1;

static gint ett_netalive = -1;
static gint ett_netalive_header = -1;
static gint ett_netalive_length = -1;
static gint ett_netalive_type = -1;
static gint ett_netalive_text = -1;

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

    int i;

    for (i = 0; i < 15; i++) {

        if (!initialized) {
            data_handle = find_dissector("data");
            helen_handle = create_dissector_handle(dissect_helen, proto_helen);

            dissector_add("udp.port", ports[i], helen_handle);
        }
    }

}

void proto_reg_handoff_netalive(void) {
    static gboolean isinitialized = FALSE;
    int i;

    for (i = 0; i < 1; i++) {

        if (!isinitialized) {
            netalivedata_handle = find_dissector("data");
            netalive_handle = create_dissector_handle(dissect_netalive, proto_netalive);
        }
        dissector_add("udp.port", global_netalive_port, netalive_handle);

    }

}

void proto_register_helen(void) {
    /* A header field is something you can search/filter on.
     *
     * This creates a structure to register our fields. It consists of an
     * array of hf_register_info structures, each of which are of the format
     * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
     */
    static hf_register_info hf[] = {
        { &hf_helen,
            { "Data", "helen.data", FT_NONE, BASE_NONE, NULL, 0x0,
                "HELEN PDU", HFILL}},
        { &hf_helen_magic,
            { "Magic Number", "helen.header", FT_BYTES, BASE_NONE, NULL, 0x0,
                "HELEN Header", HFILL}},

        { &hf_helen_checksum,
            { "Checksum", "helen.header", FT_UINT64, BASE_DEC, NULL, 0x0,
                "HELEN Header", HFILL}},

        { &hf_helen_txTime,
            { "System Tx Time", "helen.header", FT_UINT64, BASE_DEC, NULL, 0x0,
                "HELEN Header", 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}},
        { &hf_helen_Flowname,
            { "Flowname", "helen.flowname", FT_STRING, BASE_NONE, NULL, 0x0,
                "HELEN Header", HFILL}}
    };

    static gint * ett[] = {
        &ett_helen,
        &ett_helen_header,
        &ett_helen_length,
        &ett_helen_type,
        &ett_helen_text,
        &ett_helen_Flowname,
    };

    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);
}

void proto_register_netalive(void) {
    /* A header field is something you can search/filter on.
     *
     * This creates a structure to register our fields. It consists of an
     * array of hf_register_info structures, each of which are of the format
     * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
     */
    static hf_register_info hf[] = {
        { &hf_netalive,
            { "Data", "netalive.data", FT_NONE, BASE_NONE, NULL, 0x0,
                "NETALIVE PDU", HFILL}},

        { &hf_netalive_length,
            { "Net Alive Header", "netalive.len", FT_UINT16, BASE_DEC, NULL, 0x0,
                "Package Length3", HFILL}},

        { &hf_netalive_type,
            { "Type", "helen.type", FT_UINT8, BASE_DEC, VALS(packettypenames), 0x0,
                "Package Type", HFILL}},
        { &hf_netalive_text,
            { "Text", "netalive.text", FT_STRING, BASE_NONE, NULL, 0x0,
                "Text", HFILL}}
    };

    static gint * ett[] = {
        &ett_netalive,
        &ett_netalive_header,
        &ett_netalive_length,
        &ett_netalive_type,
        &ett_netalive_text,
    };

    proto_netalive = proto_register_protocol("NETALIVE", "NETALIVE", "netalive");

    proto_register_field_array(proto_netalive, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));
    register_dissector("netalive", dissect_netalive, proto_netalive);
}

static const value_string helen_vals[] = {
    {1, "GPS"},
    {2, "Flow Extension"},
    {3, "Host"},
    {1000, "Minotaur SA Extension"},
    {1002, "Minotaur SA Status Extension"},
    {1003, "Minotaur SA Redline Aspect Extension"},
    {1013, "Leger Extension"},
    {1024, "Alares Data Extension"},
    {1025, "Alares Control Extension"},
    {2000, "Channel Advertisement Packets"},
    {2001, "Interest Packets"},
    {2004, "Satcom Extension"},
    {2013, "Wave Relay Extension"},
    {2014, "Chat Extension"},
    {0, NULL}
};

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

guint32 swap24(guint32 in) {
    guint8 b2 = (in >> 16) & 0xff;
    guint8 b3 = (in >> 8) & 0xff;
    guint8 b4 = in & 0xff;
    guint32 newVal = (b4 << 16) | (b3 << 8) | b2;
    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_netalive(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

    proto_item *netalive_item = NULL;
    proto_item *netalive_sub_item = NULL;
    proto_tree *netalive_tree = NULL;
    proto_tree *netalive_header_tree = NULL;
    guint16 type = 0;
    guint8 * startOfWFBitmask;

    if (check_col(pinfo->cinfo, COL_PROTOCOL))
        col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_NETALIVE);
    /* Clear out stuff in the info column */
    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;

        netalive_item = proto_tree_add_item(tree, proto_netalive, tvb, 0, -1, FALSE);

        netalive_tree = proto_item_add_subtree(netalive_item, ett_netalive);
        netalive_header_tree = proto_item_add_subtree(netalive_item, ett_netalive);

        netalive_sub_item = proto_tree_add_item(netalive_tree, hf_netalive_length, tvb, offset, 2, FALSE);

        netalive_header_tree = proto_item_add_subtree(netalive_sub_item, ett_netalive);
        {
            guint8 * ptr = (guint8*) tvb->real_data;
            guint8 * packet_header = ptr;
            char * packet_name = "Net Alive Extension";
            proto_tree *netalive_sub_tree = NULL;
            int swap = 1;
            guint8 designator;
            guint8 version;
            guint8 updaterate;
            guint8 nodeId;
            char buf[100];
            guint32 longitude;
            guint32 latitude;
            guint32 altitude;
            guint8 altitudetype;
            guint8 radiostatus;
            guint8 networksize;
            guint16 inbound;
            guint16 outbound;
            guint32 wfModeOffset;
            guint32 wfModeNumBytes;
            int numOneBitsInMask;
            char * statusStr = "";
            char * tempStr = "";
            int codeOffset;
            ptr = packet_header;
            offset = (ptr - tvb->real_data);
            codeOffset = offset;

            strcpy(buf, " ");
            strcat(buf, packet_name);


            netalive_item = proto_tree_add_text(tree, tvb, codeOffset, 2, "%s", buf);
            netalive_sub_tree = proto_item_add_subtree(netalive_item, ett_netalive);

            //NetAlive designator
            designator = *((guint8*) ptr);
            ptr += 1;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "Net Alive Designator : %d", designator);

            offset += 1;

            //NetAlive version
            version = *((guint8*) ptr);
            ptr += 1;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "Net Alive version : %d", version);

            offset += 1;

            //NetAlive update rate
            updaterate = *((guint8*) ptr);
            ptr += 1;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "Net Alive update rate : %d", updaterate);

            offset += 1;

            //Source node ID
            nodeId = *((guint8*) ptr);
            ptr += 1;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "Source Node ID : %d", nodeId);

            offset += 1;


            //Time Stamp....
            ptr += 8;
            offset += 8;

            //GPS Latitude
            latitude = *((guint32*) ptr);
            if (swap) {
                guint32 temp = *((guint32*) ptr);
                temp = swap32(temp);
                latitude = *((guint32*) & temp);
                latitude = latitude / 10000 - 180;
            }
            ptr += 4;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 4, 0,
                    "Latitude: %d", latitude);
            offset += 4;

            //GPS Longitude
            longitude = *((guint32*) ptr);
            if (swap) {
                guint32 temp = *((guint32*) ptr);
                temp = swap32(temp);
                longitude = *((guint32*) & temp);
                longitude = longitude / 10000 - 180;
            }
            ptr += 4;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 4, 0,
                    "Longitude: %d", longitude);
            offset += 4;


            //GPS Altitude:
            altitude = *((guint32*) ptr);
            if (swap) {
                guint32 temp = *((guint32*) ptr);
                temp = swap32(temp);
                altitude = *((guint32*) & temp);
                altitude = altitude / 100;
            }
            ptr += 4;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 4, 0,
                    "Altitude: %d", altitude);
            offset += 4;

            //GPS Altitude type
            altitudetype = *((guint8*) ptr);
            if ((altitudetype & 1) == 0) {
                statusStr = "Sea Level in ";
            } else {
                statusStr = "High above ellipsoid (HAE) in ";
            }
            if ((altitudetype & 2) == 0) {
                tempStr = "meters";
            } else {
                tempStr = "feet";
            }

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "%s%s", statusStr, tempStr);
            ptr += 1;
            offset += 1;

            //Radio status and alerts
            radiostatus = *((guint8*) ptr);
            buf[0] = (char) 0;
            if ((radiostatus & 1) == 1) {
                strcat(buf, "BIT Fail");
            } else if ((radiostatus & 2) == 1) {
                strcat(buf, "No GPS");
            } else if ((radiostatus & 4) == 1) {
                strcat(buf, "Login Alert");
            } else if (radiostatus == 0) {
                strcat(buf, "no read");
            }

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "%s", buf);
            ptr += 1;
            offset += 1;

            //Network size
            networksize = *((guint8*) ptr);
            ptr += 1;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 1, 0,
                    "Network size : %d", networksize);

            offset += 1;

            //SPARE....so I am skipping this slot.

            ptr += 1;
            offset += 1;

            //Inbound throughput
            inbound = *((guint16*) ptr);
            if (swap) {
                inbound = swap16(inbound);
            }
            ptr += 2;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 2, 0,
                    "Inbound throughput : %d", inbound);

            offset += 2;

            //Outbound throughput
            outbound = *((guint16*) ptr);
            if (swap) {
                outbound = swap16(outbound);
            }
            ptr += 2;

            proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, 2, 0,
                    "Outbound throughput : %d", outbound);

            offset += 2;

            //Waveform Bitmask
            startOfWFBitmask = ptr;
            numOneBitsInMask = 0;
            {
                int i;
                char buf2[10];
                int numBytes = numBytesInBitmask(networksize);

                buf[0] = (char) 0;
                for (i = 0; i < numBytes; i++) {
                    guint8 val = *((guint8*) ptr);
                    if (val & 1) numOneBitsInMask++;
                    if (val & 2) numOneBitsInMask++;
                    if (val & 4) numOneBitsInMask++;
                    if (val & 8) numOneBitsInMask++;
                    if (val & 16) numOneBitsInMask++;
                    if (val & 32) numOneBitsInMask++;
                    if (val & 64) numOneBitsInMask++;
                    if (val & 128) numOneBitsInMask++;
                    sprintf(buf2, "%x", val);
                    strcat(buf, buf2);
                    ptr++;
                }
                proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, numBytes, 0,
                        "Waveform Bitmask : %s", buf);
                offset += numBytes;
            }


            //Waveform Mode
            {
                int i;
                char buf2[10];
                int numBytes = numBytesInMode(numOneBitsInMask);

                buf[0] = (char) 0;
                for (i = 0; i < numBytes; i++) {
                    guint8 val = *((guint8*) ptr);
                    sprintf(buf2, "%x", val);
                    strcat(buf, buf2);
                    ptr++;
                }
                wfModeOffset = offset;
                wfModeNumBytes = numBytes;
                proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, offset, numBytes, 0,
                        "Waveform Mode : %s", buf);
                offset += numBytes;
            }

            {
                guint8 *p2 = startOfWFBitmask;
                unsigned char maskByte;
                char * buf3;

                int bitmaskSize = (networksize - 1) / 8 + 1;
                int i;
                int counter = 0;

                int *indexes = malloc(sizeof (int) * bitmaskSize);

                for (i = 0; i < bitmaskSize; i++) {
                    maskByte = *p2;
                    p2++;

                    if ((maskByte & 0x1) > 0) {
                        indexes[counter++] = 1 + 8 * i;
                    }

                    if ((maskByte & 0x2) > 0) {
                        indexes[counter++] = 2 + 8 * i;
                    }

                    if ((maskByte & 0x4) > 0) {
                        indexes[counter++] = 3 + 8 * i;
                    }

                    if ((maskByte & 0x8) > 0) {
                        indexes[counter++] = 4 + 8 * i;
                    }

                    if ((maskByte & 0x10) > 0) {
                        indexes[counter++] = 5 + 8 * i;
                    }

                    if ((maskByte & 0x20) > 0) {
                        indexes[counter++] = 6 + 8 * i;
                    }

                    if ((maskByte & 0x40) > 0) {
                        indexes[counter++] = 7 + 8 * i;
                    }

                    if ((maskByte & 0x80) > 0) {
                        indexes[counter++] = 8 + 8 * i;
                    }
                }

		#define MAX_WFMode_LEN 30
                buf3 = malloc(counter * (MAX_WFMode_LEN));
                *(buf3) = (char) 0;
                if (counter > 0) {
                    int j;
                    char buf4[30];
                    int bytesToRead = (counter - 1) / 2 + 1;
                    for (j = 0; j < bytesToRead; j++) {
                        if (counter > j * 2 + 1) //read whole byte counter
                        {
                            int lowerByte = *p2 & 0x0F;
                            int upperByte = (*p2 & 0xF0) >> 4;
                            sprintf(buf4, "Node #%d: %s\n", indexes[j * 2], translateWFMode(lowerByte));
                            strcat(buf3, buf4);
                            sprintf(buf4, "Node #%d: %s\n", indexes[j * 2 + 1], translateWFMode(upperByte));
                            strcat(buf3, buf4);
                        } else //read only first 4 bits
                        {
                            int lowerByte = *p2 & 0x0F;
                            sprintf(buf4, "Node #%d: %s\n", indexes[j * 2], translateWFMode(lowerByte));
                            strcat(buf3, buf4);
                        }
                        p2++;
                    }
                }
                proto_tree_add_uint_format(netalive_sub_tree, hf_netalive_length, tvb, wfModeOffset, wfModeNumBytes, 0,
                        "Additional Information:\n%s", buf3);


                free(buf3);
                free(indexes);
            }

        }
    }
}

char * translateWFMode(int val) {
    if (val == 0) return "(0) BPSK 1(1/2)";
    if (val == 1) return "(1) BPSK 1(3/4)";
    if (val == 2) return "(2) BPSK 2";
    if (val == 3) return "(3) BPSK 4";
    if (val == 4) return "(4) QPSK 4";
    if (val == 5) return "(5) QPSK 6";
    if (val == 15) return "None";
    return "Unknown Waveform Mode";
}

int numBytesInBitmask(int numBits) {
    int q = numBits / 8;
    int extraBits = numBits % 8;
    if (extraBits > 0) {
        q++;
    }
    return q;
}

int numBytesInMode(int numBits) {
    int q = numBits / 2;
    int extraBits = numBits % 2;

    if (extraBits > 0) {
        q++;
    }
    return q;
}

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);
    /* Clear out stuff in the info column */
    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_clear(pinfo->cinfo, COL_INFO);
    }

    type = tvb_get_guint8(tvb, 4); // Get the type byte


    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) { /* we are being asked for details */
        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_sub_item = proto_tree_add_item(helen_tree, hf_helen_magic, tvb, 0, 2, FALSE);
        helen_sub_item = proto_tree_add_item(helen_tree, hf_helen_checksum, tvb, 2, 8, FALSE);

        helen_sub_item = proto_tree_add_item(helen_tree, hf_helen_txTime, tvb, 10, 8, FALSE);

        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[1000];
            char * packet_name = "";
            proto_tree *helen_sub_tree = NULL;
            int 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;
                int unknownPacket = 0;
                int 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;
                    case 1002: packet_name = "Minotaur SA Status Ext";
                        break;
                    case 1003: packet_name = "Minotaur SA Redline Aspect Ext";
                        break;
                    case 1013: packet_name = "Leger Ext";
                        break;
                    case 1024: packet_name = "Alares Data Ext";
                        break;
                    case 1025: packet_name = "Alares Control Ext";
                        break;
                    case 2000: packet_name = "Channel Advertisement Packets";
                        break;
                    case 2001: packet_name = "Interest Packets";
                        break;
                    case 2004: packet_name = "Satcom Extension";
                        break;
                    case 2013: packet_name = "Wave Relay Ext";
                        break;
                    case 2014: packet_name = "Chat Ext";
                        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:
                    if ((fieldsAvail & 2) != 0) {
                        time_t now;
                        struct tm *ts;
                        char buf[80];
                        now = time(NULL);
                        ptr += 8;
                        ts = localtime(&now);
                        strftime(buf, sizeof (buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                                "%s", buf);
                        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;
                    guint32 src;

                    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;

                    if (numBytes == 16) {
                        // Source:
                        src = *((guint32*) ptr);
                        if (swap) {
                            src = swap32(src);
                        }
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Source : %d", src);
                        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;
                    } else {
                        guint32 addr1, addr2, addr3, addr4;

                        addr1 = *((guint32*) ptr);
                        ptr += 4;
                        addr2 = *((guint32*) ptr);
                        ptr += 4;
                        addr3 = *((guint32*) ptr);
                        ptr += 4;
                        addr4 = *((guint32*) ptr);
                        ptr += 4;
                        if (swap) {
                            addr1 = swap32(addr1);
                            addr2 = swap32(addr2);
                            addr3 = swap32(addr3);
                            addr4 = swap32(addr4);
                        }

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

                //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;
                }

                //Minotaur SA Status Ext:
                if (code == 1002) {
                    guint32 stuff;
                    stuff = *((guint32*) ptr);
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, numBytes, 0,
                            "Minotaur Status Ext:");
                    offset += numBytes;
                }

                //Minotaur SA Redline Aspect Ext:
                if (code == 1003) {
                    guint32 stuff;
                    stuff = *((guint32*) ptr);

                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Minotaur SA Redline Aspect:");
                    offset += 4;
                }

                //Leger Ext:
                if (code == 1013) {
                    guint32 stuff;
                    stuff = *((guint32*) ptr);
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Leger Ext:");
                    offset += 4;
                }

                //Alares Data Ext:
                if (code == 1024) {
                    glong key;
                    guint32 id;
                    guint32 messageId;
                    guint32 totalBlks;
                    guint32 blockId;
                    glong theTime;
                    guint8 repairStatus;
                    char * repairStatusStr = "";

                    //Alares Session Key
                    if (swap) {
                        guint32 temp = *((guint32*) ptr);
                        temp = swap32(temp);
                        *((guint32*) ptr) = temp;

                        temp = *((guint32*) (ptr + 4));
                        temp = swap32(temp);
                        *((guint32*) ptr + 4) = temp;
                    }
                    key = *((glong*) ptr);
                    ptr += 8;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                            "Alares Session Key: %ld", key);
                    offset += 8;


                    //ID for Source
                    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,
                            "ID for source #: %d", id);
                    offset += 4;


                    //Message ID
                    messageId = *((guint32*) ptr);
                    if (swap) {
                        messageId = swap32(messageId);
                    }
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Message ID: %d", messageId);
                    offset += 4;


                    //Total Blocks
                    totalBlks = *((guint32*) ptr);
                    if (swap) {
                        totalBlks = swap32(totalBlks);
                    }
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Total Blocks: %d", totalBlks);
                    offset += 4;


                    //Tx Time
                    if (swap) {
                        guint32 temp = *((guint32*) ptr);
                        temp = swap32(temp);
                        *((guint32*) ptr) = temp;

                        temp = *((guint32*) (ptr + 4));
                        temp = swap32(temp);
                        *((guint32*) ptr + 4) = temp;
                    }
                    theTime = *((glong*) ptr);
                    ptr += 8;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                            "Tx Time: %ld", theTime);
                    offset += 8;


                    //Block ID
                    blockId = *((guint32*) ptr);
                    if (swap) {
                        blockId = swap32(blockId);
                    }
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Block ID #: %d", blockId);
                    offset += 4;


                    //Is Repair
                    repairStatus = *((guint8*) ptr);
                    if (repairStatus == 0) {
                        repairStatusStr = "Not Repair";
                    } else if (repairStatus == 1) {
                        repairStatusStr = "Repair";
                    }
                    ptr += 1;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "%s", repairStatusStr);

                    offset += 1;

                }

                //Chat
                if (code == 2014) {
                    guint32 nodeid;
                    guint8 messagetype;
                    guint8 messagepriority;
                    char * statusStr = "";
                    guint16 sizeofroomname;
                    char roomname[50];
                    char message[1000];
                    guint16 sizeofmessagestring;
                    int i;
                    buf[0] = (char) 0;

                    //Node ID
                    nodeid = *((guint32*) ptr);
                    if (swap) {
                        nodeid = swap32(nodeid);
                    }
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Node ID: %d", nodeid);
                    offset += 4;

                    //Message Type
                    messagetype = *((guint8*) ptr);
                    if (messagetype == 1) {
                        statusStr = "This is a Message";
                    } else if (messagetype == 2) {
                        statusStr = "This is a New Room";
                    }

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "%s", statusStr);
                    ptr += 1;
                    offset += 1;

                    //Message Payload
                    if (messagetype == 1) {

                        //Size of room name
                        sizeofroomname = *((guint16*) ptr);
                        if (swap) {
                            sizeofroomname = swap16(sizeofroomname);
                        }
                        ptr += 2;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 2, 0,
                                "Size of Room Name : %d", sizeofroomname);
                        offset += 2;

                        //Room Name
                        for (i = 0; i < sizeofroomname; i++) {
                            guint8 val = *((guint8*) ptr);
                            roomname[0] = val;
                            roomname[1] = (char) 0;
                            strcat(buf, roomname);
                            ptr++;
                        }
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, sizeofroomname, 0,
                                "Room Name : %s", buf);
                        offset += sizeofroomname;


                        //Size of message string
                        sizeofmessagestring = *((guint16*) ptr);
                        if (swap) {
                            sizeofmessagestring = swap16(sizeofmessagestring);
                        }
                        ptr += 2;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 2, 0,
                                "Size of Message String : %d", sizeofmessagestring);
                        offset += 2;



                        //Message Text:
                        buf[0] = (char) 0;
                        for (i = 0; i < sizeofmessagestring; i++) {
                            guint8 val = *((guint8*) ptr);
                            message[0] = val;
                            message[1] = (char) 0;

                            if (sizeofmessagestring < 1000) {
                                strcat(buf, message);
                            } else {
                                message[1000 - 1] = (char) 0;
                                strcat(buf, message);
                            }

                            ptr++;
                        }
                        //ptr ++;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, sizeofmessagestring, 0,
                                "Message Text: %s", buf);
                        offset += sizeofmessagestring;



                        //Message Priority
                        messagepriority = *((guint8*) ptr);
                        if (messagepriority == 0) {
                            statusStr = "Routine";
                        } else if (messagepriority == 2) {
                            statusStr = "Immediate";
                        } else if (messagepriority == 5) {
                            statusStr = "Priority";
                        } else if (messagepriority == 7) {
                            statusStr = "Flash";
                        }

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Message Priority: %s", statusStr);
                        ptr += 1;
                        offset += 1;

                    } else if (messagetype == 2) {

                        //Size of room name
                        sizeofroomname = *((guint16*) ptr);
                        if (swap) {
                            sizeofroomname = swap16(sizeofroomname);
                        }
                        ptr += 2;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 2, 0,
                                "Size of New Room Name : %d", sizeofroomname);
                        offset += 2;

                        //Room Name
                        for (i = 0; i < sizeofroomname; i++) {
                            guint8 val = *((guint8*) ptr);
                            roomname[0] = val;
                            roomname[1] = (char) 0;
                            strcat(buf, roomname);
                            ptr++;
                        }
                        //ptr ++;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, sizeofroomname, 0,
                                "Room Name : %s", buf);
                        offset += sizeofroomname;

                    }

                }

                //Channel Advertisement Packets
                if (code == 2000) {
                    guint32 serverId;
                    guint8 numofchannels;
                    int i;
                    int j;
                    int k;
                    int l;
                    int m;

                    //Server ID
                    serverId = *((guint32*) ptr);
                    if (swap) {
                        serverId = swap32(serverId);
                    }
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Server ID : %d", serverId);

                    offset += 4;

                    //Number of channels
                    numofchannels = *((guint8*) ptr);

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "Number of channels: %d", numofchannels);
                    ptr += 1;
                    offset += 1;

                    //Channel Description
                    for (i = 0; i < numofchannels; i++) {
                        guint16 uuidmostsign1;
                        guint16 uuidmostsign2;
                        guint16 uuidlesssign1;
                        guint16 uuidlesssign2;

                        guint8 errorprotectiontype;
                        char * errorprotectiontypeStr = "";
                        guint8 namesize;
                        char name[25];
                        guint8 groupsize;
                        char multicastgroup[25];
                        guint32 port;
                        guint8 serverdatasize;
                        char serverdata[50];
                        guint8 numofusers;
                        guint32 userid;

                        //UUID Most Significant
                        uuidmostsign1 = *((guint16*) ptr);
                        ptr += 4;
                        uuidmostsign2 = *((guint16*) ptr);
                        ptr += 4;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                                "UUID Most Significant: %04x-%04x", uuidmostsign1, uuidmostsign2);
                        offset += 8;

                        //UUID Less Significant
                        uuidlesssign1 = *((guint16*) ptr);
                        ptr += 4;
                        uuidlesssign2 = *((guint16*) ptr);
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                                "UUID Least Significant: %04x-%04x", uuidlesssign1, uuidlesssign2);
                        offset += 8;


                        //Error protection type
                        errorprotectiontype = *((guint8*) ptr);
                        if (errorprotectiontype == 0) {
                            errorprotectiontypeStr = "None";
                        } else if (errorprotectiontype == 1) {
                            errorprotectiontypeStr = "Norm";
                        } else if (errorprotectiontype == 2) {
                            errorprotectiontypeStr = "DFCore";
                        }

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Error Protection Type is: %s", errorprotectiontypeStr);

                        ptr += 1;
                        offset += 1;

                        //Name size
                        namesize = *((guint8*) ptr);
                        ptr += 1;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Channel Name size : %d", namesize);

                        offset += 1;

                        //NAME
                        buf[0] = (char) 0;
                        for (j = 0; j < namesize; j++) {
                            guint8 val = *((guint8*) ptr);
                            name[0] = val;
                            name[1] = (char) 0;
                            strcat(buf, name);
                            ptr++;
                        }

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, namesize, 0,
                                "Channel Advertisement Name : %s", buf);
                        offset += namesize;


                        //Group size
                        groupsize = *((guint8*) ptr);
                        ptr += 1;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Multicast Group size : %d", groupsize);

                        offset += 1;

                        //Multicast Group
                        buf[0] = (char) 0;
                        for (k = 0; k < groupsize; k++) {
                            guint8 val = *((guint8*) ptr);
                            multicastgroup[0] = val;
                            multicastgroup[1] = (char) 0;
                            strcat(buf, multicastgroup);
                            ptr++;
                        }

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, groupsize, 0,
                                "Channel Advertisement Multicast Group : %s", buf);
                        offset += groupsize;


                        //Port
                        port = *((guint32*) ptr);
                        if (swap) {
                            port = swap32(port);
                        }
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Channel Advertisement Port : %d", port);

                        offset += 4;

                        //Server data size
                        serverdatasize = *((guint8*) ptr);
                        ptr += 1;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Server Data Size : %d", serverdatasize);

                        offset += 1;

                        //Server Data
                        buf[0] = (char) 0;
                        for (l = 0; l < serverdatasize; l++) {
                            guint8 val = *((guint8*) ptr);
                            serverdata[0] = val;
                            serverdata[1] = (char) 0;
                            strcat(buf, serverdata);
                            ptr++;
                        }

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, serverdatasize, 0,
                                "Server Data : %s", buf);
                        offset += serverdatasize;

                        //Number of Users
                        numofusers = *((guint8*) ptr);
                        ptr += 1;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Number of Users : %d", numofusers);

                        offset += 1;

                        for (m = 0; m < numofusers; m++) {
                            //User ID
                            userid = *((guint32*) ptr);

                            if (swap) {
                                userid = swap32(userid);
                            }

                            ptr += 4;

                            proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                    "ID(s) of User subscribed: %d", userid);

                            offset += 4;
                        }

                    }
                }

                //Interest Packets
                if (code == 2001) {
                    guint32 clientid;
                    guint8 numofchanofinterest;
                    guint32 channelidofinterest;
                    guint8 numofchanofuninterest;
                    guint32 channelidofuninterest;

                    //Client ID
                    clientid = *((guint32*) ptr);
                    ptr += 4;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                            "Client ID : %d", clientid);

                    offset += 4;

                    //Number of channels of interest
                    numofchanofinterest = *((guint8*) ptr);

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "Number of channels of interest: %d", numofchanofinterest);
                    ptr += 1;
                    offset += 1;

                    //Channel ID of Interest
                    channelidofinterest = *((guint32*) ptr);
                    ptr += 16;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 16, 0,
                            "Channel ID of Interest: %d", channelidofinterest);

                    offset += 16;

                    //Number of channels of uninterest
                    numofchanofuninterest = *((guint8*) ptr);

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "Number of channels of uninterest: %d", numofchanofuninterest);
                    ptr += 1;
                    offset += 1;

                    //Channel ID of Uninterest
                    channelidofuninterest = *((guint32*) ptr);
                    ptr += 16;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 16, 0,
                            "Channel ID of Uninterest: %d", channelidofuninterest);

                    offset += 16;
                }

                //Satcom Extension
                if (code == 2004) {

                    guint8 status;
                    char * statusStr = "";
                    char * statusStr1 = "";
                    guint16 numberoflinks;
                    guint16 i;

                    //temp time variables.
                    time_t now;
                    struct tm *ts;
                    char buf[80];
                    now = time(NULL);
                    ts = localtime(&now);
                    strftime(buf, sizeof (buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);

                    //status
                    status = *((guint8*) ptr);
                    if (status == 0) {
                        statusStr = "Good Satcom link";
                    } else if (status == 1) {
                        statusStr = "Satcom link is Stale / Not Read";
                    }

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "%s", statusStr);
                    ptr += 1;
                    offset += 1;

                    //Time since satcom was last read
                    ptr += 8;
                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                            "Time satcom was last read: %s", buf);
                    offset += 8;

                    //Number of links
                    numberoflinks = *((guint16*) ptr);
                    if (swap) {
                        numberoflinks = swap16(numberoflinks);
                    }
                    ptr += 2;
                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 2, 0,
                            "Number of Links : %d", numberoflinks);
                    offset += 2;

                    //Harmonice ID that has satcom link
                    for (i = 0; i < numberoflinks; i++) {
                        guint32 hassatcomlink;
                        hassatcomlink = *((guint32*) ptr);
                        if (swap) {
                            hassatcomlink = swap32(hassatcomlink);
                        }

                        ptr += 4;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Harmonice ID that has satcom link: %d", hassatcomlink);
                        offset += 4;
                    }
                }

                //Wave Relay
                if (code == 2013) {
                    guint8 status;
                    guint32 mac;
                    guint8 numofrec;
                    guint32 macaddr;
                    guint32 snr;
                    char * statusStr = "";
                    int i;

                    //status
                    status = *((guint8*) ptr);
                    if (status == 0) {
                        statusStr = "Status is Good";
                    } else if (status == 1) {
                        statusStr = "Status is Stale / Not Read";
                    }

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "%s", statusStr);
                    ptr += 1;
                    offset += 1;

                    //Reporting MAC
                    mac = *((guint32*) (ptr - 1));
                    mac >>= 8;

                    if (swap) {
                        mac = swap24(mac);
                    }

                    ptr += 3;
                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 3, 0,
                            "Reporting Nodes MAC  : %06x", mac);

                    offset += 3;


                    //Number of records
                    numofrec = *((guint8*) ptr);
                    ptr += 1;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "Number of Records : %d", numofrec);

                    offset += 1;


                    //OLSR Node Information
                    for (i = 0; i < numofrec; i++) {
                        macaddr = *((guint32*) ptr);
                        if (swap) {
                            macaddr = swap24(macaddr);
                        }
                        mac >>= 8;
                        ptr += 3;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 3, 0,
                                "MAC Address of Remote Node: %06x", macaddr);

                        offset += 3;

                        //SNR
                        snr = *((guint32*) ptr);
                        ptr += 4;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "SNR : %d", snr);

                        offset += 4;
                    }

                }

                //Alares Control Ext:
                if (code == 1025) {
                    glong key;
                    guint32 id;
                    gdouble healFac;
                    guint8 noem;
                    guint8 noe;
                    guint32 src;
                    guint32 message;
                    guint32 start;
                    guint32 end;
                    int index1, index2;

                    //Alares Session Key
                    if (swap) {
                        guint32 temp = *((guint32*) ptr);
                        temp = swap32(temp);
                        *((guint32*) ptr) = temp;

                        temp = *((guint32*) (ptr + 4));
                        temp = swap32(temp);
                        *((guint32*) ptr + 4) = temp;
                    }
                    key = *((glong*) ptr);
                    ptr += 8;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                            "Alares Session Key: %ld", key);
                    offset += 8;

                    //Unique ID for Source
                    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,
                            "Unique ID for source: %d", id);
                    offset += 4;


                    //Healing Factor
                    if (swap) {
                        guint32 temp = *((guint32*) ptr);
                        temp = swap32(temp);
                        *((guint32*) ptr) = temp;

                        temp = *((guint32*) (ptr + 4));
                        temp = swap32(temp);
                        *((guint32*) ptr + 4) = temp;
                    }
                    healFac = *((gdouble*) ptr);

                    ptr += 8;

                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                            "Healing Factor: %e", healFac);

                    offset += 8;


                    //Number of Erasures in Message
                    noem = *((guint8*) ptr);
                    proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                            "Number of Erasures in Message: %d", noem);
                    ptr += 1;
                    offset += 1;

                    for (index1 = 0; index1 < noem; index1++) {
                        //Missing Data

                        //Source
                        src = *((guint32*) ptr);
                        if (swap) {
                            src = swap32(src);
                        }
                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                "Source of Missing Data: %d", src);
                        offset += 4;


                        //Message
                        message = *((guint32*) ptr);
                        ptr += 4;
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, numBytes, 0,
                                "Missing Data Message:");
                        offset += numBytes;

                        //Number of Erasures
                        noe = *((guint8*) ptr);
                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 1, 0,
                                "Number of Erasures: %d", noe);
                        ptr += 1;
                        offset += 1;

                        for (index2 = 0; index2 < noe; index2++) {
                            //Erasures

                            //Starting Block
                            start = *((guint32*) ptr);
                            if (swap) {
                                start = swap32(start);
                            }
                            ptr += 4;

                            proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                    "Starting Block: %d", start);
                            offset += 4;

                            //Ending Block
                            end = *((guint32*) ptr);
                            if (swap) {
                                end = swap32(end);
                            }
                            ptr += 4;

                            proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                                    "Ending Block: %d", end);
                            offset += 4;
                        }
                    }
                }
                packet_header += numBytes + 4;
            }
        }
        offset += 4;
        offset += 1;
    }
}