Ethereal-dev: [Ethereal-dev] TCP stream over multiple packets dissector

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: alok <alokdube@xxxxxxxxxx>
Date: Mon, 22 Nov 2004 13:08:46 +0530
Hi,

this is a half complete dissector am working on a mix of LFAP v1 and LFAP v5 (the latest revision)
(would appreciate comments on coding methods on the same)

I have a problem i cant seem to figure out the api for.

I have a TCP data stream which is split across 2 packets/frames.

What i need to do is run the dissector across the "2 packets".
In other words, I get the Information version and length in packet 1 but I need to go further down and dissect over the remaining packet.

Any suggestions on what is the best method? can i push something/leftover from previous stream into the tvb etc?

-thanks
Alok
/* packet-lfap.c
 * Routines for lfap packet dissection
 * if it doesnt work you can yell at: Alok Dube alokdube@xxxxxxxxxx
 *
 * $Id: packet-lfap.c 11410 2004-07-18 18:06:47Z gram $
 *
 * Ethereal - Network traffic analyzer
 * By Gerald Combs <gerald@xxxxxxxxxxxx>
 * Copyright 1998 Gerald Combs
 *
 * Copied from packet-tftp.c
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
#include <epan/strutil.h>
#include <epan/conversation.h>
#include "packet-wap.h"

static int proto_lfap = -1;
static int hf_lfap_version = -1;
static int hf_lfap_code = -1;
static int hf_lfap_code_v1 = -1;
static int hf_lfap_reserved = -1;
static int hf_lfap_status = -1;
static int hf_lfap_status_v1 = -1;
static int hf_lfap_message_id = -1;
static int hf_lfap_message_length = -1;
static int hf_lfap_ie_type = -1;
static int hf_lfap_ie_length = -1;
static int hf_lfap_ie_value = -1;
static int hf_lfap_ie_type1_value_addr_family_number= -1;
static int hf_lfap_ie_type1_value_addr_length= -1;
static gint ett_lfap = -1;
static gint ett_lfap_reqresp = -1;

static guint8 version;
static guint8 code;

/*code_types for version 1 in RFC 2124*/

#define          FAR_V1 1
#define          FAA_V1 2
#define          FAU_V1 3
#define          FUN_V1 4
#define          FUA_V1 5
#define          FCR_V1 6
#define          FCA_V1 7
#define           AR_V1 8
#define          ARA_V1 9
static const value_string code_types_v1[]=   {
        { FAR_V1 , "FAR" },
        { FAA_V1 , "FAA" },
        { FAU_V1 , "FAU" },
        { FUN_V1 , "FUN" },
        { FUA_V1 , "FUN" },
        { FCR_V1 , "FCR" },
        { FCA_V1 , "FCA" },
        { AR_V1  , "AR"  },
        { ARA_V1 , "AR"  },        
        }    ;





/*codes for version 5*/
#define  VR   1 /* type Code will never change in future revisions of LFAP*/
#define  VRA  2 /* type Code will never change in future revisions of LFAP*/
#define  CR   3
#define  CAN  4
#define  CRN  5
#define  FER  6
#define  FAR  7
#define  FUN  8
#define  AR   9
#define  ARA  10
#define  KA   11
#define  DR   12

/*version 5 string value pairs*/
static const value_string code_types[]=   {
        { VR  , "VRR" },
        { VRA , "VRA" },
        { CR  , "CR " },
        { CAN , "CAN" },
        { CRN , "CRN" },
        { FER , "FER" },
        { FAR , "FAR" },
        { FUN , "FUN" },        
        { AR  , "AR"  },
        { ARA , "ARA" },
        { KA  , "KA"  },
        { DR  , "DR"  }        
        }    ;

static guint8 reserved;
static guint8 status;

/*status types for version 1*/
#define   SUCCESS_V1    0
#define   CORRUPTED_V1  1
#define   VERSION_V1 2
static const value_string status_types_v1[]=   {
        { SUCCESS_V1 , "SUCCESS" },
        { CORRUPTED_V1, "CORRUPTED"},
        { VERSION_V1 , "VERSION" },
        }   ;


/*status types for version 5*/
#define SUCCESS    1
#define LFAPVERSION  2
static const value_string status_types[]=   {
        { SUCCESS , "SUCCESS" },
        { LFAPVERSION , "VERSION" }
        }   ;

static guint16  message_id;
static guint16 message_length;

static struct {
   guint16 type;
   guint16 length;
/*   void *value ; */
   gchar *value;
   } ie ; /*type length value of information element structure */

/*version 5 structures for IE types*/

/*for ie.type=1*/
static struct {
    guint16 addr_family_number;
    guint16 addr_length;
    gchar *address ;
    } ie_type1_value ;

/*for ie.type=2*/
static struct {
    guint16 len_fixed_info;
    guint16 len_record_format;
    gchar  *fixed_info;
    gchar  *record_format;
    guint16 record ; /*this field is used recursively till end of ie.length*/
    } ie_type2_value ;    

 

           

#define TCP_PORT_LFAP			3145

/*static gboolean response_is_continuation(const guchar *data);*/

static void
dissect_lfap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
        conversation_t *conversation;
        void *conv_data;
/*        gboolean        is_request;
        gboolean	is_continuation;*/
        proto_tree      *lfap_tree;
	proto_item	*ti;
  guint32  available_bytes = 0;
	guint32		offset = 0;


/* sub dissection based on data, start marking conversations*/
conversation = find_conversation(&pinfo->src, &pinfo->dst, pinfo->ptype,
                                     pinfo->srcport, pinfo->destport, 0);
    if (!conversation)
    {
        /* create a new conversation */
        conversation = conversation_new(&pinfo->src, &pinfo->dst, pinfo->ptype,
                                        pinfo->srcport, pinfo->destport, 0);
    }
  conv_data = conversation_get_proto_data(conversation, proto_lfap);

	if (check_col(pinfo->cinfo, COL_PROTOCOL))
		col_set_str(pinfo->cinfo, COL_PROTOCOL, "LFAP");

 /* clear the the info column */
    if (check_col(pinfo->cinfo, COL_INFO))
        col_clear(pinfo->cinfo, COL_INFO);

	if (tree)
    {



/* create display subtree for the protocol */

    ti = proto_tree_add_item(tree, proto_lfap, tvb, 0, -1, FALSE);
    lfap_tree = proto_item_add_subtree(ti, ett_lfap);


/*    proto_tree_add_boolean_hidden(lfap_tree, hf_lfap_main, tvb, 0, 0, TRUE);*/


    available_bytes= tvb_length_remaining(tvb,0);

    version = tvb_get_guint8(tvb,offset);
    proto_tree_add_uint(lfap_tree, hf_lfap_version, tvb, offset, 1, version);
    offset ++  ;

    if (version == 5 )
    {
    code = tvb_get_guint8(tvb,offset);
    proto_tree_add_uint(lfap_tree, hf_lfap_code, tvb, offset, 1, code);
    offset ++ ;
    }
    else
    {
    code = tvb_get_guint8(tvb,offset);
    proto_tree_add_uint(lfap_tree, hf_lfap_code_v1, tvb, offset, 1, code);
    offset ++ ;
    }
    reserved = tvb_get_guint8(tvb,offset);
    proto_tree_add_uint(lfap_tree, hf_lfap_reserved, tvb, offset, 1, reserved);
    offset ++ ;

    if (version == 5)
    {
    status = tvb_get_guint8(tvb,offset);
/*    if (check_col(pinfo->cinfo, COL_INFO))
    col_append_fstr(pinfo->cinfo, COL_INFO, "Status= %s", status_types[status]);*/
    proto_tree_add_uint(lfap_tree, hf_lfap_status, tvb, offset, 1, status);
    offset ++ ;
    }
    else
    {
    status = tvb_get_guint8(tvb,offset);
/*    if (check_col(pinfo->cinfo, COL_INFO))
    col_append_fstr(pinfo->cinfo, COL_INFO, "Status= %s", status_types[status]);*/
    proto_tree_add_uint(lfap_tree, hf_lfap_status_v1, tvb, offset, 1, status);
    offset ++ ;
    }
    message_id = tvb_get_ntohs(tvb,offset);
/*    if (check_col(pinfo->cinfo, COL_INFO))
    col_append_fstr(pinfo->cinfo, COL_INFO, "Message_Id= %d", message_id);*/
    proto_tree_add_uint(lfap_tree, hf_lfap_message_id, tvb, offset, 2, message_id);
    offset =offset+2 ;

    message_length = tvb_get_ntohs(tvb,offset);
    proto_tree_add_uint(lfap_tree, hf_lfap_message_length, tvb, offset, 2, message_length);
    offset =offset+2 ;

    fprintf (stderr, "Available-Bytes = %d, offset = %d \n", available_bytes, offset);             

        
    while (available_bytes > offset)
    {    
      ie.type = tvb_get_ntohs(tvb,offset);
      proto_tree_add_uint(lfap_tree, hf_lfap_ie_type, tvb, offset, 2, ie.type);
      offset=offset+2;
    
       fprintf (stderr, "Available-Bytes = %d, offset = %d \n", available_bytes, offset);  
       if (available_bytes > offset)
       {    
        ie.length = tvb_get_ntohs(tvb,offset);
        proto_tree_add_uint(lfap_tree, hf_lfap_ie_length, tvb, offset, 2, ie.length);
        offset=offset+2;
       }
         fprintf (stderr, "Available-Bytes = %d, offset = %d, ie.length= %d \n", available_bytes, offset, ie.length);  
    /*ie->value =  tvb_get_ptr (tvb,offset,ie.length);
 any sub dissectors for ie.value will come here*/
      if (available_bytes > offset )
      {    
        
/* dissect for version 5 IE type 1*/
        if (ie.type==1)
          {
            ie_type1_value.addr_family_number = tvb_get_ntohs(tvb,offset);
            proto_tree_add_uint(lfap_tree, hf_lfap_ie_type1_value_addr_family_number, tvb, offset, 2, ie_type1_value.addr_family_number);
            offset = offset+2 ;

            ie_type1_value.addr_length = tvb_get_ntohs (tvb,offset);
            proto_tree_add_uint(lfap_tree, hf_lfap_ie_type1_value_addr_length, tvb, offset, 2, ie_type1_value.addr_length);
            offset = offset+2;

            ie_type1_value.address = tvb_bytes_to_str (tvb,offset,ie_type1_value.addr_length);
          }
        else
          {
            ie.value= tvb_bytes_to_str ( tvb, offset , ie.length);
            proto_tree_add_string(lfap_tree, hf_lfap_ie_value, tvb, offset, ie.length, ie.value);
            offset=offset+ie.length;
          }
       }

    } /*while ends here*/
                                                                             

    } /*tree ends here*/

}


void
proto_register_lfap(void)
{

  static hf_register_info hf[] = {

      { &hf_lfap_version,
      { "Version",           "lfap.version",
	FT_UINT8, BASE_DEC, NULL, 0x0,
      	"LFAP version", HFILL }},

      { &hf_lfap_code_v1,
      { "Code",           "lfap.code",
	FT_UINT8, BASE_DEC, VALS(code_types_v1), 0x0,
      	"LFAP code", HFILL }},
       
      { &hf_lfap_code,
      { "Code",           "lfap.code",
	FT_UINT8, BASE_DEC, VALS(code_types), 0x0,
      	"LFAP code", HFILL }},

      { &hf_lfap_reserved,
      { "Reserved",           "lfap.reserved",
	FT_UINT8, BASE_DEC, NULL, 0x0,
      	"LFAP Reserved", HFILL }},

      { &hf_lfap_status_v1,
      { "Status",           "lfap.status",
	FT_UINT8, BASE_DEC, VALS(status_types_v1), 0x0,
      	"LFAP Status", HFILL }},
             
      { &hf_lfap_status,
      { "Status",           "lfap.status",
	FT_UINT8, BASE_DEC, VALS(status_types), 0x0,
      	"LFAP Status", HFILL }},

      { &hf_lfap_message_id,
      { "Message-ID",           "lfap.message_id",
	FT_UINT16, BASE_DEC, NULL, 0x0,
      	"LFAP Message ID", HFILL }},

      { &hf_lfap_message_length,
      { "Message-Length",           "lfap.message_length",
	FT_UINT16, BASE_DEC, NULL, 0x0,
      	"LFAP Length", HFILL }},


       { &hf_lfap_ie_type,
      { "IE-type",           "lfap.ie.type",
	FT_UINT16, BASE_DEC, NULL, 0x0,
      	"IE Type", HFILL }},


       { &hf_lfap_ie_length,
      { "IE-Length",           "lfap.ie.length",
	FT_UINT16, BASE_DEC, NULL, 0x0,
      	"IE Length", HFILL }},

      { &hf_lfap_ie_value,
      { "IE-Value",           "lfap.ie.value",
	      FT_STRING, BASE_NONE, NULL, 0x0,
      	"IE Value", HFILL }},

         { &hf_lfap_ie_type1_value_addr_family_number,
      { "IE-Type-1-Address-family",           "lfap.ie.type1.address_family_number",
	      FT_UINT16, BASE_DEC, NULL, 0x0,
      	"IE-Type-1-Address-family ", HFILL }},

         { &hf_lfap_ie_type1_value_addr_length,
      { "IE-Type-1-Address-length",           "lfap.ie.type1.address_length",
	      FT_UINT16, BASE_DEC, NULL, 0x0,
      	"IE-Type-1-Address-length ", HFILL }},                                                        
    /*{ &hf_lfap_request,
      { "Request",            "lfap.request",
	FT_BOOLEAN, BASE_NONE, NULL, 0x0,
      	"TRUE if lfap request", HFILL }}*/
  };
  static gint *ett[] = {
    &ett_lfap,
   /* &ett_lfap_reqresp,*/
  };

  proto_lfap = proto_register_protocol("Lighweight Flow Admission protocol", "LFAP", "lfap");
  proto_register_field_array(proto_lfap, hf, array_length(hf));
  proto_register_subtree_array(ett, array_length(ett));
}

void
proto_reg_handoff_lfap(void)
{
  dissector_handle_t lfap_handle;

  lfap_handle = create_dissector_handle(dissect_lfap, proto_lfap);
  dissector_add("tcp.port", TCP_PORT_LFAP, lfap_handle);
 }