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

From: Brian Oleksa <oleksab@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 23 Nov 2009 14:22:06 -0500
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);

//You now put your ports in the ports file
//this port can be changed to whatever port SA is running on.
//static int global_helen_port = 7636;
static int ports[16] = {5000, 5220, 42250, 50000, 5221, 5222, 49901, 49501, 49510, 42251, 42250, 56797, 5226, 47001, 5227, 7636};
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_header = -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_helen_header = -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 portnumber;
	int i;

    //FILE *fp;
//#if defined(_WIN32)
    //fp = fopen("ports.txt", "r");
//#else
	//fp = fopen("ports", "r");
//#endif

    //if (fp == NULL) {
     //   printf("Can't open the ports file! \n");
     //   printf("Make sure the file exists where the wireshark executable lives at \n");
     //   exit(1);
    //}
    	//while (fscanf(fp, "%d\n", &portnumber) != EOF) {

	//for (int i = 0; i < 15; i++)
	for(i=0; i<15; i++){
        //printf("Port number = %d\n", portnumber);

        if (!initialized) {
            data_handle = find_dissector("data");
            helen_handle = create_dissector_handle(dissect_helen, proto_helen);
            //This is to be used for hard coded ports (see static variable above)
            //dissector_add("udp.port", global_helen_port, helen_handle);

            //This line read the port number from the file.
            dissector_add("udp.port", ports[i], helen_handle);
        }
    }

   //fclose(fp);
}

void proto_reg_handoff_netalive(void) {
    static gboolean isinitialized = FALSE;
    //gboolean isnetalivefilehere = TRUE;
    //int netaliveportnumber;
    int i;

    //FILE *fpnetalive;

//#if defined(_WIN32)
//    fpnetalive = fopen("netaliveport.txt", "r");
//#else
//    fpnetalive = fopen("netaliveport", "r");
//#endif

//    if (fpnetalive == NULL) {
//        printf("Can't open the netalive ports file! \n");
//        printf("Make sure the file exists where the wireshark executable lives at \n");
//        isnetalivefilehere = FALSE;
        //exit(1);
//    }

//if netalive ports file is there....then go into this loop.
//if it is not there then just continue on.
//   if(isnetalivefilehere)
//   {
//    while (fscanf(fpnetalive, "%d\n", &netaliveportnumber) != EOF) {
for(i=0; i<1; i++)
{
//        printf("Net Alive Port number = %d\n", netaliveportnumber);

        if (!isinitialized) {
            netalivedata_handle = find_dissector("data");
            netalive_handle = create_dissector_handle(dissect_netalive, proto_netalive);
	}
            //This line read the port number from the file.
            dissector_add("udp.port", global_netalive_port, netalive_handle);
        //}

}
//     fclose(fpnetalive);
   }

    //fclose(fpnetalive);
    //isinitialized = TRUE;
//}


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_HEX, 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"}

};

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

//time converter method here
//int txTime()
//{
//   time_t now;
//   struct tm *ts;
//   char buf[80];

//   now = time(NULL);

//   ts = localtime(&now);
//   return strftime(buf, sizeof (buf), "%a %Y-%m-%d %H:%M:%S %Z", ts);

//return value;
//}

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

    // This is not a good way of dissecting packets.  The tvb length should
    // be sanity checked so we aren't going past the actual size of the buffer.
    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;

        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];
                //glong timestamp;
                //gfloat longitude;
                //gfloat latitude;
                guint32 longitude;
                guint32 latitude;
                //gfloat lat_n;
                //gfloat altitude;
                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);
             // Hardcoding to ALWAYS SWAP as we don't know how to detect when to swap!


//                if (swap) {
//                    code = swap16(code);
//                }
//
//                ptr += 1;
//                offset += 1;
//                numBytes = *((guint16*) ptr);
//                if (swap) {
//                    numBytes = swap16(numBytes);
//                }
                //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....
                //this is just getting system time....and not the time off the radio.
                //However...the radios time should be the same at the system time
                //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(netalive_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                //         "%s", buf);
                offset += 8;

                //GPS Latitude
                latitude = *((guint32*) ptr);
                if (swap) {
                    guint32 temp = *((guint32*) ptr);
                    temp = swap32(temp);
                    latitude = *((guint32*) & temp);
		     //this needs to be tested
		    latitude = latitude/10000 - 180;
		    //don't think this is the right calculation
		    //latitude = (latitude+180) *10000;
                }
                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 = *((gfloat*) ptr);
                longitude = *((guint32*) ptr);
                if (swap) {
                    guint32 temp = *((guint32*) ptr);
                    temp = swap32(temp);
                    //longitude = *((gfloat*) & temp);
                    longitude = *((guint32*) & temp);
		  //this needs to be tested
		    longitude = longitude/10000 - 180;
                }
                ptr += 4;

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


                //GPS Altitude:
                //altitude = *((gfloat*) ptr);
                altitude = *((guint32*) ptr);
                if (swap) {
                    guint32 temp = *((guint32*) ptr);
                    temp = swap32(temp);
                    //altitude = *((gfloat*) & 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);
                        //"Altitude: %f", 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");
                }
                // We could rip out the ending comma (if it exists!) by trying the following:
                //{
                    //char* p2; // Put this at the top!

                    //if (strlen(buf) > 0) {
                    //   p2 = buf + strlen(buf) - 1;
                    //   *p2 = (char)0;
                    //}
                //}

                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);
		        // This would be nice:
		        //  17: BPSK 4
			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;

				//hard coding networkSize
				 // int networkSize = 26;

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

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


  //need to loop through size
    for (i = 0; i < bitmaskSize; i++)
  	{
          maskByte=*p2;
  	p2++;

  		if ((maskByte & 0x1) > 0)
  		{
                      indexes[counter++] = 1 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x2) > 0)
  		{
                      indexes[counter++] = 2 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x4) > 0)
  		{
                      indexes[counter++] = 3 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x8) > 0)
  		{
                      indexes[counter++] = 4 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x10) > 0)
  		{
                      indexes[counter++] = 5 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x20) > 0)
  		{
                      indexes[counter++] = 6 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x40) > 0)
  		{
                      indexes[counter++] = 7 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}

  		if ((maskByte & 0x80) > 0)
  		{
                      indexes[counter++] = 8 + 8*i;
  		    //printf("Read in maskByte of 0x%x\n",maskByte);
  		}
  	}

  	//printf("We have %d nodes, and here they are:\n", counter);
  	//for (i = 0; i < counter; i++){
  	//	printf("\t%d\n", indexes[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++ ) {
  		//printf("counter = %d, and j = %d, bytesToRead = %d\n", counter, j, bytesToRead);
  		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);
    }

    // This is not a good way of dissecting packets.  The tvb length should
    // be sanity checked so we aren't going past the actual size of the buffer.
    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_header, tvb, offset, -1, FALSE);
        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);
        //need to format the time..!!
        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;
            //might need this in the netalive code..??
            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;
                // Must re-set the offset because of Flow control messages that specify only 12 bytes, but actually contain 16:
                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, "Packet Code ");
                strcpy(buf, " ");
                strcat(buf, packet_name);
                if (unknownPacket) {
                    sprintf(buf, "Unknown packet: %d", code);
                }

                //might need this in the net alive 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;

                    //printf("%s \n", "This is the GPS Extension");

                    // 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: ...This is the first attempt at time
                    //if ( (fieldsAvail & 2) != 0) {
                    //guint32 halfTime1, halfTime2;
                    //halfTime1 = *((guint32*)ptr);
                    //ptr += 4;
                    //halfTime2 = *((guint32*)ptr);
                    //ptr += 4;

                    //scanf("%X",halfTime1);
                    //printf("%f",halfTime1);

                    //proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 8, 0,
                    //  "Time: %X %X", halfTime1, halfTime2);
                    //offset += 8;
                    //}


                    // Time:
                    //this is just getting system time....and not the time of the GPS.
                    //However...the GPS time should be the same at the system 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 is NOT available or less than or equal to zero...then do not display it.
                        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;

                    //printf("This is the Flow Extension\n");

                    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;

                    //printf("%s \n", "This is the Host Extension");

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

                    //I was board so I added the IPv6 address translation here in this else statement....However..I cannot test it..but it should work.
                    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;
                    //printf("%s \n", "This is the Minotaur SA Ext");
                    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;
                    //printf("%s \n", "This is the Minotaur SA Status Ext");
                    stuff = *((guint32*) ptr);
                    //if (swap){
                    //    id = swap32(id);
                    //}
                    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:
                //Need more info.. Need size and data types
                if (code == 1003) {
                    guint32 stuff;
                    //printf("%s \n", "This is the Minotaur SA Redline Aspect Ext");
                    stuff = *((guint32*) ptr);
                    //if (swap){
                    //    id = swap32(id);
                    //}
                    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:
                //Need more info.. Need size and data types
                if (code == 1013) {
                    guint32 stuff;
                    //printf("%s \n", "This is the Leger Ext");
                    stuff = *((guint32*) ptr);
                    //if (swap){
                    //    id = swap32(id);
                    //}
                    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 = "";

                    //time_t rightnow;
                    //struct tme *tss;
                    //char buff[80];
                    //rightnow = time(NULL);
                    //tss = localtime(&rightnow);

                    //printf("%s \n", "This is the Alares Data Ext");

                    //Alares Session Key
                    if (swap) {
                        // 64-bit swap, done as 2 32-bit swaps in the
                        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) {
                        // 64-bit swap, done as 2 32-bit swaps in the
                        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;
		    //printf("%s \n", "This is the CHAT Ext");

		    //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++;
			}
			//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 uuidmostsign3;
						//guint16 uuidmostsign4;
						//guint16 uuidmostsign5;
						//guint32 uuidmostsign6;

						guint16 uuidlesssign1;
						guint16 uuidlesssign2;
						//guint16 uuidlesssign3;
						//guint16 uuidlesssign4;
						//guint16 uuidlesssign5;
						//guint32 uuidlesssign6;

						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;
					//uuidmostsign3 = *((guint16*) ptr);
					//ptr+= 2;
					//uuidmostsign4 = *((guint16*) ptr);
					//ptr+= 2;
					//uuidmostsign5 = *((guint16*) ptr);
					//ptr+= 2;
					//uuidmostsign6 = *((guint32*) 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;
					//uuidlesssign3 = *((guint16*) ptr);
					//ptr+= 2;
					//uuidlesssign4 = *((guint16*) ptr);
					//ptr+= 2;
					//uuidlesssign5 = *((guint16*) ptr);
					//ptr+= 2;
					//uuidlesssign6 = *((guint32*) 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
                    //this is just getting system time....and not the time of the last read from the packet.
					//this needs to be fixed but am having problems with the formatting of the time from the packet
                    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 nodeinfo;
		    		guint32 macaddr;
		    		guint32 snr;
                    char * statusStr = "";
		    		int i;

                    //printf("%s \n", "This is the Wave Relay Ext");

                    //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++) {
		        //MAC address
                        macaddr = * ((guint32*) ptr);
						//macaddr = macaddr & 0xffffff;
						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;
                    //guint32 healFac;
                    gdouble healFac;
                    guint8 noem;
                    guint8 noe;
                    guint32 src;
                    guint32 message;
                    guint32 start;
                    guint32 end;
                    int index1, index2;

                    //printf("%s \n", "This is the Alares Control Ext");

                    //Alares Session Key
                    if (swap) {
                        // 64-bit swap, done as 2 32-bit swaps in the
                        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
                        //guint32 stuff;
                        message = *((guint32*) ptr);
                        //printf("%s \n", "This is the Missing Data Message");

                        ptr += 4;

                        proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, numBytes, 0,
                                "Missing Data Message:");
                        offset += numBytes;

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

                        //proto_tree_add_uint_format(helen_sub_tree, hf_helen_length, tvb, offset, 4, 0,
                        //        "Missing Data Message: %d", message);
                        //offset += 4;
                        //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;

                        } // end of for j

                    } /* end of for i */
                }

                packet_header += numBytes + 4;

            }

        }

        offset += 4;

        offset += 1;
    }
}