Ethereal-dev: [Ethereal-dev] Diameter Finally up to -07

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

From: David Frascone <dave@xxxxxxxxxxxx>
Date: Sun, 29 Jul 2001 22:53:46 -0500
Attached is the context diffs bringing the diameter dissector up to date with
http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-07.txt

Changes:

o	Flags are now done properly.  (I changed it to dissect them like 
	packet-tcp.c does)

o	Completely re-did the dictionary.  I think it is much more maintainable
	now.  And, it is no longer dynamically generated.

o	Added some lookup routines to work with new dictionary.

o	Removed lots of old lookup stuff that had been cloned from
	packet-radius.c.  It's much cleaner now.


There are still some things missing though:

o	Only the base protocol is supported (no extensions have been added
	to the dictionary)  This is because the dictionary is hard-coded.
	An optional XML dictionary will be implemented soon, and will be
	parsed if libxml is detected in the dynamic loading path.

o	Grouped AVPs have *not* been tested after this change.  (My diameter
	implementation is not quite finished yet).  But, nothing changed,
	so it *should* still work.

I am asking for this to be checked in now, since many people have asked me for
it.  As I finish bringing my implementation up to spec, I will be able to more
fully test the dissector.


-Dave
Index: packet-diameter.c
===================================================================
RCS file: /cvsroot/ethereal/packet-diameter.c,v
retrieving revision 1.24
diff -u -c -r1.24 packet-diameter.c
*** packet-diameter.c	2001/07/15 19:14:00	1.24
--- packet-diameter.c	2001/07/30 03:44:21
***************
*** 47,72 ****
  #include "prefs.h"
  
  /* This must be defined before we include packet-diameter-defs.h s*/
- typedef struct _value_value_pair {
-         guint32 val1;
-         guint32 val2;
- } value_value_pair;
  
  /* Valid data types */
  typedef enum {
! 	DIAMETER_DATA=1,
! 	DIAMETER_STRING,
! 	DIAMETER_ADDRESS,
! 	DIAMETER_INTEGER32,
! 	DIAMETER_INTEGER64,
! 	DIAMETER_UNSIGNED32,
! 	DIAMETER_UNSIGNED64,
! 	DIAMETER_FLOAT32,
! 	DIAMETER_FLOAT64,
! 	DIAMETER_FLOAT128,
! 	DIAMETER_TIME,
! 	DIAMETER_GROUPED
! } diameterDataTypes;
  
  #include "packet-diameter-defs.h"
  
--- 47,83 ----
  #include "prefs.h"
  
  /* This must be defined before we include packet-diameter-defs.h s*/
  
  /* Valid data types */
  typedef enum {
!   /* Base Types */
!   DIAMETER_OCTET_STRING = 1,
!   DIAMETER_INTEGER32,
!   DIAMETER_INTEGER64,
!   DIAMETER_UNSIGNED32,
!   DIAMETER_UNSIGNED64,
!   DIAMETER_FLOAT32,
!   DIAMETER_FLOAT64,
!   DIAMETER_FLOAT128,
!   DIAMETER_GROUPED,
! 
!   /* Derived Types */
!   DIAMETER_IP_ADDRESS,         /* OctetString */
!   DIAMETER_TIME,               /* Integer 32 */
!   DIAMETER_UTF8STRING,         /* OctetString */
!   DIAMETER_IDENTITY,           /* OctetString */
!   DIAMETER_ENUMERATED,         /* Integer 32 */
!   DIAMETER_IP_FILTER_RULE,     /* OctetString */
!   DIAMETER_QOS_FILTER_RULE     /* OctetString */
!   
! } diameterDataType;
! 
! typedef struct avp_info {
!   guint32           code;
!   gchar            *name;
!   diameterDataType  type;
!   value_string     *values;
! } avpInfo;
  
  #include "packet-diameter-defs.h"
  
***************
*** 75,103 ****
  #define TCP_PORT_DIAMETER	1812
  #define SCTP_PORT_DIAMETER	1812
  
  static int proto_diameter = -1;
  static int hf_diameter_length = -1;
  static int hf_diameter_code = -1;
  static int hf_diameter_hopbyhopid =-1;
  static int hf_diameter_endtoendid =-1;
  static int hf_diameter_reserved = -1;
- static int hf_diameter_flags = -1;
  static int hf_diameter_version = -1;
  static int hf_diameter_vendor_id = -1;
  
  static int hf_diameter_avp_code = -1;
  static int hf_diameter_avp_length = -1;
  static int hf_diameter_avp_reserved = -1;
  static int hf_diameter_avp_flags = -1;
  static int hf_diameter_avp_vendor_id = -1;
  
  
  static int hf_diameter_avp_data_uint32 = -1;
  static int hf_diameter_avp_data_int32 = -1;
- #if 0
  static int hf_diameter_avp_data_uint64 = -1;
  static int hf_diameter_avp_data_int64 = -1;
- #endif
  static int hf_diameter_avp_data_bytes = -1;
  static int hf_diameter_avp_data_string = -1;
  static int hf_diameter_avp_data_v4addr = -1;
--- 86,137 ----
  #define TCP_PORT_DIAMETER	1812
  #define SCTP_PORT_DIAMETER	1812
  
+ static const true_false_string flags_set_truth = {
+   "Set",
+   "Not set"
+ };
+ 
+ static const true_false_string reserved_set = {
+   "*** Error! Reserved Bit is Set",
+   "Ok"
+ };
  static int proto_diameter = -1;
  static int hf_diameter_length = -1;
  static int hf_diameter_code = -1;
  static int hf_diameter_hopbyhopid =-1;
  static int hf_diameter_endtoendid =-1;
  static int hf_diameter_reserved = -1;
  static int hf_diameter_version = -1;
  static int hf_diameter_vendor_id = -1;
+ static int hf_diameter_flags = -1;
+ static int hf_diameter_flags_request = -1;
+ static int hf_diameter_flags_proxyable = -1;
+ static int hf_diameter_flags_error = -1;
+ static int hf_diameter_flags_reserved3 = -1;
+ static int hf_diameter_flags_reserved4 = -1;
+ static int hf_diameter_flags_reserved5 = -1;
+ static int hf_diameter_flags_reserved6 = -1;
+ static int hf_diameter_flags_reserved7 = -1;
  
  static int hf_diameter_avp_code = -1;
  static int hf_diameter_avp_length = -1;
  static int hf_diameter_avp_reserved = -1;
  static int hf_diameter_avp_flags = -1;
+ static int hf_diameter_avp_flags_vendor_specific = -1;
+ static int hf_diameter_avp_flags_mandatory = -1;
+ static int hf_diameter_avp_flags_protected = -1;
+ static int hf_diameter_avp_flags_reserved3 = -1;
+ static int hf_diameter_avp_flags_reserved4 = -1;
+ static int hf_diameter_avp_flags_reserved5 = -1;
+ static int hf_diameter_avp_flags_reserved6 = -1;
+ static int hf_diameter_avp_flags_reserved7 = -1;
  static int hf_diameter_avp_vendor_id = -1;
  
  
  static int hf_diameter_avp_data_uint32 = -1;
  static int hf_diameter_avp_data_int32 = -1;
  static int hf_diameter_avp_data_uint64 = -1;
  static int hf_diameter_avp_data_int64 = -1;
  static int hf_diameter_avp_data_bytes = -1;
  static int hf_diameter_avp_data_string = -1;
  static int hf_diameter_avp_data_v4addr = -1;
***************
*** 105,111 ****
--- 139,147 ----
  static int hf_diameter_avp_data_time = -1;
  
  static gint ett_diameter = -1;
+ static gint ett_diameter_flags = -1;
  static gint ett_diameter_avp = -1;
+ static gint ett_diameter_avp_flags = -1;
  static gint ett_diameter_avpinfo = -1;
  
  static char gbl_diameterString[200];
***************
*** 113,157 ****
  static int gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
  
  typedef struct _e_diameterhdr {
! 	guint8 reserved;
! 	guint8 flagsVer;
! 	guint16 pktLength;
! 	guint32 hopByHopId;
! 	guint32 endToEndId;
! 	guint32 commandCode;
! 	guint32 vendorId;
  } e_diameterhdr;
  
  typedef struct _e_avphdr {
! 	guint32 avp_code;
! 	guint16 avp_length;
! 	guint8  avp_reserved;
! 	guint8  avp_flags;
! 	guint32 avp_vendorId;           /* optional */
  } e_avphdr;
  
  #define AUTHENTICATOR_LENGTH 12
  
  /* Diameter Header Flags */
  #define DIAM_FLAGS_E 0x20
! #define DIAM_FLAGS_I 0x10
! #define DIAM_FLAGS_R 0x08
! #define DIAM_FLAGS_RESERVED 0xc0         /* 11000000  -- X X E I R V V V */
  
  /* Diameter AVP Flags */
! #define AVP_FLAGS_P 0x0020
! #define AVP_FLAGS_V 0x0004
! #define AVP_FLAGS_M 0x0001
! #define AVP_FLAGS_RESERVED 0xea          /* 11101010  -- X X X P X V X M */
  
  #define MIN_AVP_SIZE (sizeof(e_avphdr) - sizeof(guint32))
  #define MIN_DIAMETER_SIZE (sizeof(e_diameterhdr) + MIN_AVP_SIZE)
  
- static gchar *rd_value_to_str(e_avphdr *avph,const u_char *input, int length);
  static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
- static guint32 match_numval(guint32 val, const value_value_pair *vs);
- static gchar *DetermineMessageType(char flagsVer);
  
  /* Code to actually dissect the packets */
  
  /*
--- 149,274 ----
  static int gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
  
  typedef struct _e_diameterhdr {
!   guint32  versionLength;
!   guint32  flagsCmdCode;
!   guint32  vendorId;
!   guint32  hopByHopId;
!   guint32  endToEndId;
  } e_diameterhdr;
  
  typedef struct _e_avphdr {
!   guint32 avp_code;
!   guint32 avp_flagsLength;
!   guint32 avp_vendorId;           /* optional */
  } e_avphdr;
  
  #define AUTHENTICATOR_LENGTH 12
  
  /* Diameter Header Flags */
+ /*                                      RPrrrrrrCCCCCCCCCCCCCCCCCCCCCCCC  */
+ #define DIAM_FLAGS_R 0x80
+ #define DIAM_FLAGS_P 0x40
  #define DIAM_FLAGS_E 0x20
! #define DIAM_FLAGS_RESERVED3 0x10
! #define DIAM_FLAGS_RESERVED4 0x08
! #define DIAM_FLAGS_RESERVED5 0x04
! #define DIAM_FLAGS_RESERVED6 0x02
! #define DIAM_FLAGS_RESERVED7 0x01
! #define DIAM_FLAGS_RESERVED  0x1f
! 
! #define DIAM_LENGTH_MASK  0x00ffffffl
! #define DIAM_COMMAND_MASK DIAM_LENGTH_MASK
! #define DIAM_GET_FLAGS(dh)                ((dh.flagsCmdCode & ~DIAM_COMMAND_MASK) >> 24)
! #define DIAM_GET_VERSION(dh)              ((dh.versionLength & (~DIAM_LENGTH_MASK)) >> 24)
! #define DIAM_GET_COMMAND(dh)              (dh.flagsCmdCode & DIAM_COMMAND_MASK)
! #define DIAM_GET_LENGTH(dh)               (dh.versionLength & DIAM_LENGTH_MASK)
  
  /* Diameter AVP Flags */
! #define AVP_FLAGS_P 0x20
! #define AVP_FLAGS_V 0x80
! #define AVP_FLAGS_M 0x40
! #define AVP_FLAGS_RESERVED3 0x10
! #define AVP_FLAGS_RESERVED4 0x08
! #define AVP_FLAGS_RESERVED5 0x04
! #define AVP_FLAGS_RESERVED6 0x02
! #define AVP_FLAGS_RESERVED7 0x01
! #define AVP_FLAGS_RESERVED 0x1f          /* 00011111  -- V M P X X X X X */
  
  #define MIN_AVP_SIZE (sizeof(e_avphdr) - sizeof(guint32))
  #define MIN_DIAMETER_SIZE (sizeof(e_diameterhdr) + MIN_AVP_SIZE)
  
  static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
  
+ 
+ 
+ 
+ /* Diameter Manipulation Routines (mess with our strucutres) */
+ 
+ diameterDataType
+ diameter_avp_get_type(guint32 avpCode){
+   int i;
+   for (i=0; diameter_avps[i].name; i++) {
+ 	if (avpCode == diameter_avps[i].code) {
+ 	  /* We found it! */
+ 	  return diameter_avps[i].type;
+ 	}
+   }
+   /* If we don't find it, assume it's data */
+   g_warning("DIAMETER: Unable to find type for avpCode %d!", avpCode);
+   return DIAMETER_OCTET_STRING;
+ } /* diameter_avp_get_type */
+ 
+ static gchar *
+ diameter_avp_get_name(guint32 avpCode)
+ {
+   static gchar buffer[64];
+ 
+   int i;
+   for (i=0; diameter_avps[i].name; i++) {
+ 	if (avpCode == diameter_avps[i].code) {
+ 	  /* We found it! */
+ 	  return diameter_avps[i].name;
+ 	}
+   }
+   /* If we don't find it, build a name string */
+   sprintf(buffer, "Unknown AVP:0x%08x", avpCode);
+   return buffer;
+ } /* diameter_avp_get_name */
+ static gchar *
+ diameter_avp_get_value(guint32 avpCode, guint32 avpValue)
+ {
+   static gchar buffer[64];
+ 
+   int i;
+   for (i=0; diameter_avps[i].name; i++) {
+ 	if (avpCode == diameter_avps[i].code) {
+ 	  /* We found the code.  Now find the value! */
+ 	  if (!diameter_avps[i].values) 
+ 		break;
+ 	  return val_to_str(avpValue, diameter_avps[i].values , "Unknown Value: 0x%08x");
+ 	}
+   }
+   /* If we don't find the avp, build a value string */
+   sprintf(buffer, "Unknown AVP! Value: 0x%08x", avpValue);
+   return buffer;
+ } /* diameter_avp_get_value */
+ 
+ static gchar *
+ diameter_time_to_string(gchar *timeValue)
+ {
+   static gchar buffer[64];
+   int intval;
+   struct tm lt;
+ 
+   intval=pntohl(*((guint32*)timeValue));
+   intval -= NTP_TIME_DIFF;
+   lt=*localtime((time_t *)&intval);
+   strftime(buffer, 1024, 
+ 		   "%a, %d %b %Y %H:%M:%S %z",&lt);
+   return buffer;
+ } /* diameter_time_to_string */
+ 
+ 
  /* Code to actually dissect the packets */
  
  /*
***************
*** 160,308 ****
  static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  {
  
! /* Set up structures needed to add the protocol subtree and manage it */
! 	proto_item *ti;
! 	tvbuff_t        *avp_tvb;
! 	proto_tree *diameter_tree;
! 	e_diameterhdr dh;
! 	char *codestrval;
! 	size_t offset=0;
! 	size_t avplength;
! 	proto_tree *avp_tree;
! 	proto_item *avptf;
! 	int BadPacket = FALSE;
! 	
! /* Make entries in Protocol column and Info column on summary display */
! 	if (check_col(pinfo->fd, COL_PROTOCOL)) 
! 		col_add_str(pinfo->fd, COL_PROTOCOL, "Diameter");
! 	if (check_col(pinfo->fd, COL_INFO)) 
! 		col_clear(pinfo->fd, COL_INFO);
  	
! 	/* Copy our header */
! 	tvb_memcpy(tvb, (guint8*) &dh, offset, sizeof(dh));
  	
! 	/* Fix byte ordering in our static structure */
! 	dh.pktLength = ntohs(dh.pktLength);
! 	dh.hopByHopId = ntohl(dh.hopByHopId);
! 	dh.endToEndId = ntohl(dh.endToEndId);
! 	
! 	dh.commandCode = ntohl(dh.commandCode);
! 	dh.vendorId = ntohl(dh.vendorId);
! 	
! 	codestrval=  match_strval(dh.commandCode,diameter_command_code_vals);
! 	if (codestrval==NULL) {
! 		codestrval="Unknown Command Code";
! 	}
! 
! 	/* Short packet.  Should have at LEAST one avp */
! 	if (dh.pktLength < MIN_DIAMETER_SIZE) {
! 		g_warning("DIAMETER: Packet too short: %d bytes less than min size (%d bytes))",
! 			dh.pktLength, MIN_DIAMETER_SIZE);
! 		BadPacket = TRUE;
! 	}
! 
! 	/* And, check our reserved flags/version */
! 	if (dh.reserved || (dh.flagsVer & DIAM_FLAGS_RESERVED) ||
! 		((dh.flagsVer & 0x7) != 1)) {
! 		g_warning("DIAMETER: Bad packet: Bad Flags or Version");
! 		BadPacket = TRUE;
! 	}
! 
! 	if (check_col(pinfo->fd, COL_INFO)) {
! 		col_add_fstr(pinfo->fd, COL_INFO,
! 		    "%s%s: %s(%d) vendor=%d (hop-id=%d) (end-id=%d) EIR=%d%d%d",
! 		    (BadPacket)?"***** Bad Packet!: ":"",
! 		    DetermineMessageType(dh.flagsVer),
! 		    codestrval, dh.commandCode, dh.vendorId,
! 		    dh.hopByHopId, dh.endToEndId,
! 		    (dh.flagsVer & DIAM_FLAGS_E)?1:0,
! 		    (dh.flagsVer & DIAM_FLAGS_I)?1:0,
! 		    (dh.flagsVer & DIAM_FLAGS_R)?1:0);
! 	}
! 	
! 
! /* In the interest of speed, if "tree" is NULL, don't do any work not
!    necessary to generate protocol tree items. */
! 	if (tree) {
! 
! /* create display subtree for the protocol */
! 		ti = proto_tree_add_item(tree, proto_diameter, tvb, offset, tvb_length(tvb), FALSE);
! 		diameter_tree = proto_item_add_subtree(ti, ett_diameter);
! 
! 		/* Reserved */
! 		proto_tree_add_uint(diameter_tree, hf_diameter_reserved, tvb, offset, 1, dh.reserved);
! 		offset +=1;
! 
! 		/* Flags */
! 		proto_tree_add_uint_format(diameter_tree,
! 		    hf_diameter_flags,
! 		    tvb, offset, 1,
! 		    dh.flagsVer,
! 		    "Packet flags: 0x%02x  E:%d I:%d R:%d (%s)",
! 		    (dh.flagsVer&0xf8)>>3,
! 		    (dh.flagsVer & DIAM_FLAGS_E)?1:0,
! 		    (dh.flagsVer & DIAM_FLAGS_I)?1:0,
! 		    (dh.flagsVer & DIAM_FLAGS_R)?1:0,
! 		    DetermineMessageType(dh.flagsVer));
! 
! 		/* Version */
! 		proto_tree_add_uint(diameter_tree,
! 		    hf_diameter_version,
! 		    tvb, offset, 1,
! 		    dh.flagsVer);
! 
! 		offset+=1;
  
- 		
- 		/* Length */
- 		proto_tree_add_uint(diameter_tree,
- 		    hf_diameter_length, tvb,
- 		    offset, 2, dh.pktLength);
- 		offset +=2;
- 
- 		/* Hop-by-hop Identifier */
- 		proto_tree_add_uint(diameter_tree, hf_diameter_hopbyhopid,
- 		    tvb, offset, 4, dh.hopByHopId);
- 		offset += 4;
  
! 		/* End-to-end Identifier */
! 		proto_tree_add_uint(diameter_tree, hf_diameter_endtoendid,
! 		    tvb, offset, 4, dh.endToEndId);
! 		offset += 4;
  
! 		/* Command Code */
! 		proto_tree_add_uint(diameter_tree, hf_diameter_code,
! 		    tvb, offset, 4, dh.commandCode);
! 		offset += 4;
  
! 		/* Vendor Id */
! 		proto_tree_add_uint(diameter_tree,hf_diameter_vendor_id,
! 		    tvb, offset, 4,
! 		    dh.vendorId);
! 		offset += 4;
  
! 		/* If we have a bad packet, don't bother trying to parse the AVPs */
! 		if (BadPacket) {
! 			return;
! 		}
  
! 		/* Start looking at the AVPS */
! 		/* Make the next tvbuff */
  
! 		/* Update the lengths */
! 		avplength= dh.pktLength - sizeof(e_diameterhdr);
      
! 		avp_tvb = tvb_new_subset(tvb, offset, -1, avplength);
! 		avptf = proto_tree_add_text(diameter_tree,
! 		    tvb, offset, tvb_length(tvb),
! 		    "Attribute Value Pairs");
  		
! 		avp_tree = proto_item_add_subtree(avptf,
! 		    ett_diameter_avp);
! 		if (avp_tree != NULL) {
! 			dissect_avps( avp_tvb, pinfo, avp_tree);
! 		}
  	}
  } /* dissect_diameter */
  
  /*
--- 277,466 ----
  static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  {
  
!   /* Set up structures needed to add the protocol subtree and manage it */
!   proto_item      *ti;
!   proto_item      *tf;
!   proto_tree      *flags_tree;
!   tvbuff_t        *avp_tvb;
!   proto_tree      *diameter_tree;
!   e_diameterhdr    dh;
!   size_t           offset=0;
!   size_t           avplength;
!   proto_tree      *avp_tree;
!   proto_item      *avptf;
!   int              BadPacket = FALSE;
!   guint32          commandCode, pktLength;
!   guint8           version, flags;
!   gchar            flagstr[64] = "<None>";
!   gchar           *fstr[] = {"RSVD7", "RSVD6", "RSVD5", "RSVD4", "RSVD3", "Error", "Proxyable", "Request" };
!   gchar            commandString[64], vendorString[64];
!   gint        i;
!   guint      bpos;
  	
!   /* Make entries in Protocol column and Info column on summary display */
!   if (check_col(pinfo->fd, COL_PROTOCOL)) 
! 	col_add_str(pinfo->fd, COL_PROTOCOL, "Diameter");
!   if (check_col(pinfo->fd, COL_INFO)) 
! 	col_clear(pinfo->fd, COL_INFO);
  	
!   /* Copy our header */
!   tvb_memcpy(tvb, (guint8*) &dh, offset, sizeof(dh));
! 	
!   /* Fix byte ordering in our static structure */
!   dh.versionLength = ntohl(dh.versionLength);
!   dh.flagsCmdCode = ntohl(dh.flagsCmdCode);
!   dh.vendorId = ntohl(dh.vendorId);
!   dh.hopByHopId = ntohl(dh.hopByHopId);
!   dh.endToEndId = ntohl(dh.endToEndId);
! 
!   if (dh.vendorId) {
! 	strcpy(vendorString, 
! 		   val_to_str(dh.vendorId, diameter_vendor_specific_vendors, "Unknown Vendor: %08x"));
!   } else {
! 	strcpy(vendorString, "None");
!   }
  
  
!   /* Do the bit twiddling */
!   version = DIAM_GET_VERSION(dh);
!   pktLength = DIAM_GET_LENGTH(dh);
!   flags = DIAM_GET_FLAGS(dh);
!   commandCode = DIAM_GET_COMMAND(dh);
! 
!   /* Set up our flags */
!   if (check_col(pinfo->fd, COL_INFO) || tree) {  
! 	flagstr[0]=0;
! 	for (i = 0; i < 8; i++) {
! 	  bpos = 1 << i;
! 	  if (flags & bpos) {
! 		if (flagstr[0]) {
! 		  strcat(flagstr, ", ");
! 		}
! 		strcat(flagstr, fstr[i]);
! 	  }
! 	}
! 	if (strlen(flagstr) == 0) {
! 	  strcpy(flagstr,"<None>");
! 	}
!   }
!   
!   /* Set up our commandString */
!   strcpy(commandString, val_to_str(commandCode, diameter_command_code_vals, "Unknown Command: 0x%08x"));
!   if (flags & DIAM_FLAGS_R) 
! 	strcat(commandString, "-Request");
!   else
! 	strcat(commandString, "-Answer");
! 
!   /* Short packet.  Should have at LEAST one avp */
!   if (pktLength < MIN_DIAMETER_SIZE) {
! 	g_warning("DIAMETER: Packet too short: %d bytes less than min size (%d bytes))",
! 			  pktLength, MIN_DIAMETER_SIZE);
! 	BadPacket = TRUE;
!   }
  
!   /* And, check our reserved flags/version */
!   if ((flags & DIAM_FLAGS_RESERVED) ||
! 	  (version != 1)) {
! 	g_warning("DIAMETER: Bad packet: Bad Flags(0x%x) or Version(%u)",
! 			  flags, version);
! 	BadPacket = TRUE;
!   }
  
!   if (check_col(pinfo->fd, COL_INFO)) {
! 	col_add_fstr(pinfo->fd, COL_INFO,
! 				 "%s%s%s%s: %s vendor=%s (hop-id=%d) (end-id=%d) RPE=%d%d%d",
! 				 (BadPacket)?"***** Bad Packet!: ":"",
! 				 (flags & DIAM_FLAGS_P)?"Proxyable ":"",
! 				 (flags & DIAM_FLAGS_R)?"Request":"Answer",
! 				 (flags & DIAM_FLAGS_E)?" Error":"",
! 				 commandString, vendorString,
! 				 dh.hopByHopId, dh.endToEndId,
! 				 (flags & DIAM_FLAGS_R)?1:0,
! 				 (flags & DIAM_FLAGS_P)?1:0,
! 				 (flags & DIAM_FLAGS_E)?1:0);
!   }
! 	
  
!   /* In the interest of speed, if "tree" is NULL, don't do any work not
! 	 necessary to generate protocol tree items. */
!   if (tree) {
! 
! 	/* create display subtree for the protocol */
! 	ti = proto_tree_add_item(tree, proto_diameter, tvb, offset, tvb_length(tvb), FALSE);
! 	diameter_tree = proto_item_add_subtree(ti, ett_diameter);
! 
! 	/* Version */
! 	proto_tree_add_uint(diameter_tree,
! 						hf_diameter_version,
! 						tvb, offset, 1,
! 						version);
! 
! 	offset+=1;
! 
! 	/* Length */
! 	proto_tree_add_uint(diameter_tree,
! 						hf_diameter_length, tvb,
! 						offset, 3, pktLength);
! 	offset += 3;
! 
! 	/* Flags */
! 	tf = proto_tree_add_uint_format(diameter_tree, hf_diameter_flags, tvb,
! 									offset , 1, flags, "Flags: 0x%02x (%s)", flags,
! 									flagstr);
! 	flags_tree = proto_item_add_subtree(tf, ett_diameter_avp_flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_request, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_proxyable, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_error, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved3, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved4, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved5, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved6, tvb, offset, 1, flags);
! 	proto_tree_add_boolean(flags_tree, hf_diameter_flags_reserved7, tvb, offset, 1, flags);
! 
! 	offset += 1;
! 
! 	/* Command Code */
! 	proto_tree_add_uint_format(diameter_tree, hf_diameter_code,
! 						tvb, offset, 3, commandCode, "Command Code: %s", commandString);
! 	offset += 3;
! 
! 	/* Vendor Id */
! 	proto_tree_add_uint_format(diameter_tree,hf_diameter_vendor_id,
! 						tvb, offset, 4,	dh.vendorId, "Vendor-Id: %s", vendorString);
! 	offset += 4;
! 
! 	/* Hop-by-hop Identifier */
! 	proto_tree_add_uint(diameter_tree, hf_diameter_hopbyhopid,
! 						tvb, offset, 4, dh.hopByHopId);
! 	offset += 4;
! 
! 	/* End-to-end Identifier */
! 	proto_tree_add_uint(diameter_tree, hf_diameter_endtoendid,
! 						tvb, offset, 4, dh.endToEndId);
! 	offset += 4;
! 
! 	/* If we have a bad packet, don't bother trying to parse the AVPs */
! 	if (BadPacket) {
! 	  return;
! 	}
  
! 	/* Start looking at the AVPS */
! 	/* Make the next tvbuff */
  
! 	/* Update the lengths */
! 	avplength= pktLength - sizeof(e_diameterhdr);
      
! 	avp_tvb = tvb_new_subset(tvb, offset, -1, avplength);
! 	avptf = proto_tree_add_text(diameter_tree,
! 								tvb, offset, tvb_length(tvb),
! 								"Attribute Value Pairs");
  		
! 	avp_tree = proto_item_add_subtree(avptf,
! 									  ett_diameter_avp);
! 	if (avp_tree != NULL) {
! 	  dissect_avps( avp_tvb, pinfo, avp_tree);
  	}
+   }
  } /* dissect_diameter */
  
  /*
***************
*** 311,749 ****
   */
  static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
  {
! /* adds the attribute value pairs to the tree */
! 	e_avphdr avph;
! 	gchar *avptpstrval;
! 	gchar *valstr;
! 	guint32 vendorId=0;
! 	int hdrLength;
! 	int fixAmt;
! 	proto_tree *avpi_tree;
! 	int vendorOffset;
! 	size_t offset = 0 ;
! 	char dataBuffer[4096];
! 	tvbuff_t        *group_tvb;
! 	proto_tree *group_tree;
! 	proto_item *grouptf;
! 	proto_item *avptf;
! 	char buffer[1024];
! 	int BadPacket = FALSE;
! 	
! 	size_t packetLength;
! 	size_t avpDataLength;
! 	int avpType;
! 
! 	packetLength = tvb_length(tvb);
! 
! 	/* Check for invalid packet lengths */
! 	if (packetLength <= 0) {
! 		proto_tree_add_text(avp_tree, tvb, offset, tvb_length(tvb),
! 		    "No Attribute Value Pairs Found");
! 		return;
! 	}
  	
! 
! 	/* Spin around until we run out of packet */
! 	while (packetLength > 0 ) {
! 		vendorOffset = 0;
! 		
! 		/* Check for short packet */
! 		if (packetLength < MIN_AVP_SIZE) {
! 			g_warning("DIAMETER: AVP Payload too short: %d bytes less than min size (%d bytes))",
! 				packetLength, MIN_AVP_SIZE);
! 			BadPacket = TRUE;
! 			/* Don't even bother trying to parse a short packet. */
! 			return;
! 		}
  
! 		/* Copy our header */
! 		tvb_memcpy(tvb, (guint8*) &avph, offset, sizeof(avph));
  
! 		/* Fix the byte ordering */
! 		avph.avp_code = ntohl(avph.avp_code);
! 		avph.avp_length = ntohs(avph.avp_length);
! 
! 		/* Dissect our vendor id if it exists  and set hdr length*/
! 		if (avph.avp_flags & AVP_FLAGS_V) {
! 			vendorId = ntohl(avph.avp_vendorId);
! 			/* Vendor id */
! 			hdrLength = sizeof(e_avphdr);
! 		} else {
! 			/* No vendor */
! 			hdrLength = sizeof(e_avphdr) - 
! 			    sizeof(guint32);
! 		}
  
! 		/* Check for bad length */
! 		if (avph.avp_length < MIN_AVP_SIZE || 
! 		    (avph.avp_length > packetLength)) {
! 			g_warning("DIAMETER: AVP payload size invalid: avp_length: %d bytes,  min: %d bytes,    packetLen: %d",
! 				avph.avp_length, MIN_AVP_SIZE, packetLength);
! 			BadPacket = TRUE;
! 		}
  
! 		/* Check for bad flags */
! 		if (avph.avp_reserved || 
! 		    (avph.avp_flags & AVP_FLAGS_RESERVED)) {
! 		        g_warning("DIAMETER: Invalid AVP: avph.avp_reserved = 0x%x, avph.avp_flags = 0x%x, resFl=0x%x",
! 			avph.avp_reserved, avph.avp_flags, AVP_FLAGS_RESERVED);
! 			BadPacket = TRUE;
! 		}
  		
! 	        /*
! 		 * Fix byte-alignment (Diameter AVPs are sent on 4 byte
! 		 * boundries)
! 		 */
! 		fixAmt = 4 - (avph.avp_length % 4);
! 		if (fixAmt == 4) fixAmt = 0;
! 
! 		packetLength = packetLength - (avph.avp_length + fixAmt);
! 
! 		/* Check for out of bounds */
! 		if (packetLength < 0) {
! 		        g_warning("DIAMETER: Bad AVP: Bad new length (%d bytes)",
  				packetLength);
! 			BadPacket = TRUE;
! 		}
! 
! 		avptpstrval = match_strval(avph.avp_code, diameter_attrib_type_vals);
! 		if (avptpstrval == NULL) avptpstrval="Unknown Type";
  
! 		avptf = proto_tree_add_text(avp_tree, tvb,
! 		    offset, avph.avp_length,
! 		    "%s(%d) l:0x%x (%d bytes)",
! 		    avptpstrval, avph.avp_code, avph.avp_length,
! 		    avph.avp_length);
! 		avpi_tree = proto_item_add_subtree(avptf,
! 		    ett_diameter_avpinfo);
! 
! 		if (avpi_tree !=NULL) {
! 			/* Command Code */
! 			proto_tree_add_uint(avpi_tree, hf_diameter_avp_code,
! 			    tvb, offset, 4, avph.avp_code);
! 			offset += 4;
  		
! 			proto_tree_add_uint(avpi_tree, hf_diameter_avp_length,
! 			    tvb, offset, 2, avph.avp_length);
! 			offset += 2;
! 
! 			proto_tree_add_uint(avpi_tree, hf_diameter_avp_reserved,
! 			    tvb, offset, 1, avph.avp_reserved);
! 			offset += 1;
! 
! 			proto_tree_add_uint_format(avpi_tree,
! 			    hf_diameter_avp_flags, tvb,
! 			    offset, 1, avph.avp_flags,
! 			    "Flags: P:%d V:%d M:%d",
! 			    (avph.avp_flags & AVP_FLAGS_P)?1:0,
! 			    (avph.avp_flags & AVP_FLAGS_V)?1:0,
! 			    (avph.avp_flags & AVP_FLAGS_M)?1:0);
! 			offset += 1;
! 
! 			if (avph.avp_flags & AVP_FLAGS_V) {
! 				proto_tree_add_uint(avpi_tree, hf_diameter_avp_vendor_id,
! 				    tvb, offset, 4, avph.avp_vendorId);
! 				offset += 4;
! 			}
! 
! 			avpDataLength = avph.avp_length - hdrLength;
! 
! 			/*
! 			 * If we've got a bad packet, just highlight the data.  Don't try
! 			 * to parse it, and, don't move to next AVP.
! 			 */
! 			if (BadPacket) {
! 				offset -= hdrLength;
! 				proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 				    tvb, offset, tvb_length(tvb) - offset, dataBuffer,
! 				    "Bad AVP (Suspect Data Not Dissected)");
! 				return;
! 			}
! 
! 			avpType=match_numval(avph.avp_code, diameter_printinfo);
! 			tvb_memcpy(tvb, (guint8*) dataBuffer, offset, MIN(4095,
! 				       avph.avp_length - hdrLength));
! 			
! 			switch(avpType) {
! 			case DIAMETER_GROUPED:
! 				sprintf(buffer, "%s Grouped AVPs", avptpstrval);
! 				/* Recursively call ourselves */
! 				grouptf = proto_tree_add_text(avpi_tree,
! 				    tvb, offset, tvb_length(tvb),
! 				    buffer);
! 				
! 				group_tree = proto_item_add_subtree(grouptf,
! 				    ett_diameter_avp);
! 
! 				group_tvb = tvb_new_subset(tvb, offset,
! 				    MIN(avpDataLength, tvb_length(tvb)-offset), avpDataLength);
! 				if (group_tree != NULL) {
! 					dissect_avps( group_tvb, pinfo, group_tree);
! 				}
! 				break;
! 				
! 			case DIAMETER_STRING:
! 				proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
! 				    tvb, offset, avpDataLength, dataBuffer,
! 				    "String: %*.*s", (int)avpDataLength, (int)avpDataLength,
! 				    dataBuffer);
! 				break;
! 			case DIAMETER_ADDRESS:
! 				if (avpDataLength == 4) {
! 				        guint32 ipv4Address = ntohl((*(guint32*)dataBuffer));
! 					proto_tree_add_ipv4_format(avpi_tree, hf_diameter_avp_data_v4addr,
! 					    tvb, offset, avpDataLength, ipv4Address,
! 					    "IPv4 Address: %u.%u.%u.%u",
! 					    (ipv4Address&0xff000000)>>24,
! 					    (ipv4Address&0xff0000)>>16,
! 					    (ipv4Address&0xff00)>>8,
! 					    (ipv4Address&0xff));
! 				} else if (avpDataLength == 16) {
! 					proto_tree_add_ipv6_format(avpi_tree, hf_diameter_avp_data_v6addr,
! 					    tvb, offset, avpDataLength, dataBuffer, 
! 					    "IPv6 Address: %04x:%04x:%04x:%04x",
! 					    *((guint32*)dataBuffer),
! 					    *((guint32*)&dataBuffer[4]),
! 					    *((guint32*)&dataBuffer[8]),
! 					    *((guint32*)&dataBuffer[12]));
! 				} else {
! 					proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 					    tvb, offset, avpDataLength, dataBuffer,
! 					    "Error!  Bad Address Length");
! 				}
! 				break;
! 
! 			case DIAMETER_INTEGER32:
! 			case DIAMETER_UNSIGNED32:
! 			case DIAMETER_INTEGER64:
! 			case DIAMETER_UNSIGNED64:
! 				valstr=rd_value_to_str(&avph, dataBuffer, offset);
! 				
! 				proto_tree_add_int_format(avpi_tree, hf_diameter_avp_data_int32,
! 				    tvb, offset, avpDataLength, (*(guint32*)dataBuffer),
! 				    "Value: %s",  valstr);
! 
! 				break;
! 
! 			case DIAMETER_TIME:
! 				valstr=rd_value_to_str(&avph, dataBuffer, offset);
! 
! 				proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 				    tvb, offset, avpDataLength, dataBuffer, "Time: %s", valstr);
! 				break;
! 				
! 			default:
! 			case DIAMETER_DATA:
! 				proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 				    tvb, offset, avpDataLength, dataBuffer,
! 				    "Data");
! 				break;
! 				
! 			}
! 			offset += avph.avp_length - hdrLength;
! 		}
! 		offset += fixAmt; /* fix byte alignment */
! 	}
! } /* dissect_avps */
  
! /* Generic routine to work with value value pairs */
! static guint32 match_numval(guint32 val, const value_value_pair *vs)
! {
!   guint32 i = 0;
  
!   while (vs[i].val1) {
!     if (vs[i].val1 == val)
!       return(vs[i].val2);
!     i++;
!   }
  
!   return(0);
! }
  
! static gchar *rd_match_strval(guint32 val, const value_string *vs) {
! 	gchar		*result;
! 	result=match_strval(val,vs);
! 	if (result == NULL ) {
! 		result="Undefined";
! 	}
! 	return result;
! }
! static char *customValCheck(int code, int value)
! {
! 	switch (code) {
! 	case DIAMETER_ATT_QOS_SERVICE_TYPE:
! 		return rd_match_strval(value, diameter_qos_service_type_vals);
! 		break;
! 	case DIAMETER_ATT_SERVICE_TYPE:
! 		return rd_match_strval(value, diameter_service_type_vals);
! 		break;
! 	case DIAMETER_ATT_PROHIBIT:
! 		return rd_match_strval(value, diameter_prohibit_vals);
! 		break;
! 	case DIAMETER_ATT_PROMPT:
! 		return rd_match_strval(value, diameter_prompt_vals);
! 		break;
! 	case DIAMETER_ATT_SOURCE_PORT:
! 		return rd_match_strval(value, diameter_source_port_vals);
! 		break;
! 	case DIAMETER_ATT_NAS_PORT_TYPE:
! 		return rd_match_strval(value, diameter_nas_port_type_vals);
! 		break;
! 	case DIAMETER_ATT_INTERFACE_ADDRESS:
! 		return rd_match_strval(value, diameter_interface_address_vals);
! 		break;
! 	case DIAMETER_ATT_FRAMED_ROUTING:
! 		return rd_match_strval(value, diameter_framed_routing_vals);
! 		break;
! 	case DIAMETER_ATT_ARAP_ZONE_ACCESS:
! 		return rd_match_strval(value, diameter_arap_zone_access_vals);
! 		break;
! 	case DIAMETER_ATT_ACCT_AUTHENTIC:
! 		return rd_match_strval(value, diameter_acct_authentic_vals);
! 		break;
! 	case DIAMETER_ATT_FRAMED_PROTOCOL:
! 		return rd_match_strval(value, diameter_framed_protocol_vals);
! 		break;
! 	case DIAMETER_ATT_FRAMED_COMPRESSION:
! 		return rd_match_strval(value, diameter_framed_compression_vals);
! 		break;
! 	case DIAMETER_ATT_AUTHENTICATION_TYPE:
! 		return rd_match_strval(value, diameter_authentication_type_vals);
! 		break;
! 	case DIAMETER_ATT_ACCT_TERMINATE_CAUSE:
! 		return rd_match_strval(value, diameter_acct_terminate_cause_vals);
! 		break;
! 	case DIAMETER_ATT_PROTOCOL:
! 		return rd_match_strval(value, diameter_protocol_vals);
! 		break;
! 	case DIAMETER_ATT_DESTINATION_PORT:
! 		return rd_match_strval(value, diameter_destination_port_vals);
! 		break;
! 	case DIAMETER_ATT_TERMINATION_ACTION:
! 		return rd_match_strval(value, diameter_termination_action_vals);
! 		break;
! 	case DIAMETER_ATT_EXTENSION_ID:
! 		return rd_match_strval(value, diameter_extension_id_vals);
! 		break;
! 	case DIAMETER_ATT_MERIT_LAS_CODE:
! 		return rd_match_strval(value, diameter_merit_las_code_vals);
! 		break;
! 	case DIAMETER_ATT_LOGIN_SERVICE:
! 		return rd_match_strval(value, diameter_login_service_vals);
! 		break;
! 	case DIAMETER_ATT_RSVP_SERVICE_TYPE:
! 		return rd_match_strval(value, diameter_rsvp_service_type_vals);
! 		break;
! 	case DIAMETER_ATT_ACCT_STATUS_TYPE:
! 		return rd_match_strval(value, diameter_acct_status_type_vals);
  		break;
- 	}
  
! 	return NULL;
! }
! 
! static gchar *rd_value_to_str(e_avphdr *avph, const u_char *input, int length)
! {
! 	int print_type;
! 	guint32 intval;
! 	char *valstr;
! 	static char buffer[1024];
! 
! /* prints the values of the attribute value pairs into a text buffer */
! 	
! 	print_type=match_numval(avph->avp_code,diameter_printinfo);
! 
! 	/* Set the Default */
! 	strcpy(buffer, "Unknown Value");
  
! 	/* Default begin */
! 	switch(print_type)
  		{
! 		case DIAMETER_INTEGER32:
! 			/* Check for custom values */
! 			intval=pntohl(input);
! 			valstr=customValCheck(avph->avp_code, intval);
! 			if (valstr) {
! 				sprintf(buffer,"%s (%u)", valstr, intval);
! 			} else {
! 				sprintf(buffer,"%d", intval);
! 			}
! 			break;
! 		case DIAMETER_UNSIGNED32:
! 			/* Check for custom values */
! 			intval=pntohl(input);
! 			valstr=customValCheck(avph->avp_code, intval);
! 			if (valstr) {
! 				sprintf(buffer,"%s (%u)", valstr, intval);
! 			} else {
! 				sprintf(buffer,"%u", intval);
! 			}
! 			break;
! #ifdef G_HAVE_GINT64
! 		/* XXX - have to handle platforms without 64-bit integral
! 		   types.
! 		   Have to handle platforms where "%lld" and "%llu"
! 		   aren't the right formats to use to print 64-bit integral
! 		   types. */
! 		case DIAMETER_INTEGER64:
! 		{
! 			gint64 llval;
! 			llval = pntohll(input);
! 			sprintf(buffer,"%lld", llval);
  		}
! 			break;
! 		case DIAMETER_UNSIGNED64:
  		{
! 			guint64 llval;
! 			llval = pntohll(input);
! 			sprintf(buffer,"%llu", llval);
  		}
! 			break;
! #endif
! 		case DIAMETER_TIME:
  		{
! 			struct tm *lt;
! 			intval=pntohl(input);
! 			intval -= NTP_TIME_DIFF;
! 			lt=localtime((time_t *)&intval);
! 			if (lt != NULL) {
! 			  strftime(buffer, 1024, 
! 			           "%a, %d %b %Y %H:%M:%S %z",lt);
! 			} else {
! 			  strncpy(buffer, "Not representable", 1024);
! 			}
  		}
! 		default:
! 			/* Do nothing */
! 			;
  		}
! 	return buffer;
! } /* rd value to str */
  
! static gchar *
! DetermineMessageType(char flagsVer)
! {
! 	/* Get rid of version */
! 	flagsVer = flagsVer >> 3;
  
! 	/* Mask out reserved bits */
! 	flagsVer = flagsVer & 0x7;
  
! 	switch (flagsVer) {
! 	case 0x0: /* Indication */
! 		return "Indication";
! 	case 0x4: /* Request */
! 		return "Request";
! 	case 0x1: /* Answer */
! 		return "Answer";
! 	case 0x6: /* Query */
! 		return "Query";
! 	case 0x3: /* Reply */
! 		return "Reply";
! 	default:
! 		return "Illegal Command Type";
! 	}
! } /* DetermineMessageType */
  
  
  void
--- 469,801 ----
   */
  static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
  {
!   /* adds the attribute value pairs to the tree */
!   e_avphdr avph;
!   gchar avpTypeString[64];
!   gchar avpNameString[64];
!   gchar *valstr;
!   guint32 vendorId=0;
!   gchar    vendorString[64];
!   int hdrLength;
!   int fixAmt;
!   proto_tree *avpi_tree;
!   size_t offset = 0 ;
!   char dataBuffer[4096];
!   tvbuff_t        *group_tvb;
!   proto_tree *group_tree;
!   proto_item *grouptf;
!   proto_item *avptf;
!   char buffer[1024];
!   int BadPacket = FALSE;
!   guint32 avpLength;
!   guint8 flags;
!   proto_item      *tf;
!   proto_tree      *flags_tree;
  	
!   gint32 packetLength;
!   size_t avpDataLength;
!   int avpType;
!   gchar flagstr[64] = "<None>";
!   gchar *fstr[] = {"RSVD7", "RSVD6", "RSVD5", "RSVD4", "RSVD3", "Protected", "Mandatory", "Vendor-Specific" };
!   gint        i;
!   guint      bpos;
! 
!   packetLength = tvb_length(tvb);
! 
!   /* Check for invalid packet lengths */
!   if (packetLength <= 0) {
! 	proto_tree_add_text(avp_tree, tvb, offset, tvb_length(tvb),
! 						"No Attribute Value Pairs Found");
! 	return;
!   }
  
!   /* Spin around until we run out of packet */
!   while (packetLength > 0 ) {
  
! 	/* Check for short packet */
! 	if (packetLength < (long)MIN_AVP_SIZE) {
! 	  g_warning("DIAMETER: AVP Payload too short: %d bytes less than min size (%d bytes))",
! 				packetLength, MIN_AVP_SIZE);
! 	  BadPacket = TRUE;
! 	  /* Don't even bother trying to parse a short packet. */
! 	  return;
! 	}
! 	
! 	/* Copy our header */
! 	tvb_memcpy(tvb, (guint8*) &avph, offset, MIN((long)sizeof(avph),packetLength));
! 	
! 	/* Fix the byte ordering */
! 	avph.avp_code = ntohl(avph.avp_code);
! 	avph.avp_flagsLength = ntohl(avph.avp_flagsLength);
! 	
! 	flags = (avph.avp_flagsLength & 0xff000000) >> 24;
! 	avpLength = avph.avp_flagsLength & 0x00ffffff;
! 	
! 	/* Set up our flags string */
! 	if (check_col(pinfo->fd, COL_INFO) || avp_tree) {  
! 	  flagstr[0]=0;
! 	  for (i = 0; i < 8; i++) {
! 		bpos = 1 << i;
! 		if (flags & bpos) {
! 		  if (flagstr[0]) {
! 			strcat(flagstr, ", ");
! 		  }
! 		  strcat(flagstr, fstr[i]);
! 		}
! 	  }
! 	  if (strlen(flagstr) == 0) {
! 		strcpy(flagstr,"<None>");
! 	  }
! 	}
! 
! 	/* Dissect our vendor id if it exists  and set hdr length */
! 	if (flags & AVP_FLAGS_V) {
! 	  vendorId = ntohl(avph.avp_vendorId);
! 	  /* Vendor id */
! 	  hdrLength = sizeof(e_avphdr);
! 	} else {
! 	  /* No vendor */
! 	  hdrLength = sizeof(e_avphdr) - 
! 		sizeof(guint32);
! 	  vendorId = 0;
! 	}
  
! 	if (vendorId) {
! 	  strcpy(vendorString, 
! 			 val_to_str(vendorId, diameter_vendor_specific_vendors, "Unknown Vendor: %08x"));
! 	} else {
! 	  vendorString[0]='\0';
! 	}
  
! 	/* Check for bad length */
! 	if (avpLength < MIN_AVP_SIZE || 
! 		((long)avpLength > packetLength)) {
! 	  g_warning("DIAMETER: AVP payload size invalid: avp_length: %d bytes,  "
! 				"min: %d bytes,    packetLen: %d",
! 				avpLength, MIN_AVP_SIZE, packetLength);
! 	  BadPacket = TRUE;
! 	}
! 
! 	/* Check for bad flags */
! 	if (flags & AVP_FLAGS_RESERVED) {
! 	  g_warning("DIAMETER: Invalid AVP: Reserved bit set.  flags = 0x%x,"
! 				" resFl=0x%x",
! 				flags, AVP_FLAGS_RESERVED);
! 	  /* For now, don't set bad packet, since I'm accidentally setting a wrong bit */
! 	  // BadPacket = TRUE;
! 	}
  		
! 	/*
! 	 * Compute amount of byte-alignment fix (Diameter AVPs are sent on 4 byte
! 	 * boundries)
! 	 */
! 	fixAmt = 4 - (avpLength % 4);
! 	if (fixAmt == 4) fixAmt = 0;
! 	
! 	/* shrink our packetLength */
! 	packetLength = packetLength - (avpLength + fixAmt);
! 	
! 	/* Check for out of bounds */
! 	if (packetLength < 0) {
! 	  g_warning("DIAMETER: Bad AVP: Bad new length (%d bytes) ",
  				packetLength);
! 	  BadPacket = TRUE;
! 	}
  
! 	/* Make avp Name & type */
! 	strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code), diameter_avp_type_vals, 
! 								   "Unknown-Type: 0x%08x"));
! 	strcpy(avpNameString, diameter_avp_get_name(avph.avp_code));
! 
! 	avptf = proto_tree_add_text(avp_tree, tvb,
! 								offset, avpLength + fixAmt,
! 								"%s (%s) l:0x%x (%d bytes) (%d padded bytes)",
! 								avpNameString, avpTypeString, avpLength,
! 								avpLength, avpLength+fixAmt);
! 	avpi_tree = proto_item_add_subtree(avptf,
! 									   ett_diameter_avpinfo);
! 
! 	if (avpi_tree !=NULL) {
! 	  /* Command Code */
! 	  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_code,
! 						  tvb, offset, 4, avph.avp_code, "AVP Code: %s", avpNameString);
! 	  offset += 4;
  		
! 	  tf = proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_flags, tvb,
! 									  offset , 1, flags, "Flags: 0x%02x (%s)", flags,
! 									  flagstr);
! 	  flags_tree = proto_item_add_subtree(tf, ett_diameter_avp_flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_vendor_specific, tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_mandatory, tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_protected, tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved3,  tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved4,  tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved5,  tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved6,  tvb, offset, 1, flags);
! 	  proto_tree_add_boolean(flags_tree, hf_diameter_avp_flags_reserved7,  tvb, offset, 1, flags);
! 	  offset += 1;
! 
! 	  proto_tree_add_uint(avpi_tree, hf_diameter_avp_length,
! 						  tvb, offset, 3, avpLength);
! 	  offset += 3;
! 
! 	  if (flags & AVP_FLAGS_V) {
! 		proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_vendor_id,
! 								   tvb, offset, 4, vendorId, vendorString);
! 		offset += 4;
! 	  }
  
! 	  avpDataLength = avpLength - hdrLength;
  
! 	  /*
! 	   * If we've got a bad packet, just highlight the data.  Don't try
! 	   * to parse it, and, don't move to next AVP.
! 	   */
! 	  if (BadPacket) {
! 		offset -= hdrLength;
! 		proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 									tvb, offset, tvb_length(tvb) - offset, dataBuffer,
! 									"Bad AVP (Suspect Data Not Dissected)");
! 		return;
! 	  }
  
! 	  avpType=diameter_avp_get_type(avph.avp_code);
! 	  tvb_memcpy(tvb, (guint8*) dataBuffer, offset, MIN(4095,avpDataLength));
! 	
! 	  
! 	  switch(avpType) {
! 	  case DIAMETER_GROUPED:
! 		sprintf(buffer, "%s Grouped AVPs", avpNameString);
! 		/* Recursively call ourselves */
! 		grouptf = proto_tree_add_text(avpi_tree,
! 									  tvb, offset, tvb_length(tvb),
! 									  buffer);
! 				
! 		group_tree = proto_item_add_subtree(grouptf,
! 											ett_diameter_avp);
  
! 		group_tvb = tvb_new_subset(tvb, offset,
! 								   MIN(avpDataLength, tvb_length(tvb)-offset), avpDataLength);
! 		if (group_tree != NULL) {
! 		  dissect_avps( group_tvb, pinfo, group_tree);
! 		}
  		break;
  
! 	  case DIAMETER_IDENTITY:
! 		proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
! 									 tvb, offset, avpDataLength, dataBuffer,
! 									 "Identity: %*.*s", (int)avpDataLength, (int)avpDataLength,
! 									 dataBuffer);
! 		break;
! 	  case DIAMETER_UTF8STRING:
! 		proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
! 									 tvb, offset, avpDataLength, dataBuffer,
! 									 "UTF8String: %*.*s", (int)avpDataLength, (int)avpDataLength,
! 									 dataBuffer);
! 		break;
! 	  case DIAMETER_IP_ADDRESS:
! 		if (avpDataLength == 4) {
! 		  guint32 ipv4Address = ntohl((*(guint32*)dataBuffer));
! 		  proto_tree_add_ipv4_format(avpi_tree, hf_diameter_avp_data_v4addr,
! 									 tvb, offset, avpDataLength, ipv4Address,
! 									 "IPv4 Address: %u.%u.%u.%u",
! 									 (ipv4Address&0xff000000)>>24,
! 									 (ipv4Address&0xff0000)>>16,
! 									 (ipv4Address&0xff00)>>8,
! 									 (ipv4Address&0xff));
! 		} else if (avpDataLength == 16) {
! 		  proto_tree_add_ipv6_format(avpi_tree, hf_diameter_avp_data_v6addr,
! 									 tvb, offset, avpDataLength, dataBuffer, 
! 									 "IPv6 Address: %04x:%04x:%04x:%04x",
! 									 *((guint32*)dataBuffer),
! 									 *((guint32*)&dataBuffer[4]),
! 									 *((guint32*)&dataBuffer[8]),
! 									 *((guint32*)&dataBuffer[12]));
! 		} else {
! 		  proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 									  tvb, offset, avpDataLength, dataBuffer,
! 									  "Error!  Bad Address Length");
! 		}
! 		break;
  
! 	  case DIAMETER_INTEGER32:
  		{
! 		  gint32 data;
! 		  memcpy(&data, dataBuffer, 4);
! 		  data = ntohl(data);
! 		  proto_tree_add_int_format(avpi_tree, hf_diameter_avp_data_int32,
! 									tvb, offset, avpDataLength, data,
! 									"Value: %ld", (long int)data );
  		}
! 		break;
! 
! 	  case DIAMETER_UNSIGNED32:
  		{
! 		  guint32 data;
! 
! 		  memcpy(&data, dataBuffer, 4);
! 		  data=ntohl(data);
! 		  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
! 									 tvb, offset, avpDataLength, data,
! 									 "Value: 0x%08lx (%lu)", (long unsigned int)data,
! 									 (long unsigned int)data );
  		}
! 		break;
! 
! 	  case DIAMETER_INTEGER64:
  		{
! 		  gint64 data;
! 		  memcpy(&data, dataBuffer, 8);
! 		  /* data = ntohll(data); */
! 		  proto_tree_add_int_format(avpi_tree, hf_diameter_avp_data_int64,
! 									tvb, offset, avpDataLength, data,
! 									"Value: 0x%016llx (%lld)", (unsigned long long)data, data );
  		}
! 		break;
! 	  case DIAMETER_UNSIGNED64:
! 		{
! 		  guint64 data;
! 		  memcpy(&data, dataBuffer, 8);
! 		  /* data = ntohll(data); */
! 		  proto_tree_add_int_format(avpi_tree, hf_diameter_avp_data_uint64,
! 									tvb, offset, avpDataLength, data,
! 									"Value: 0x%016llx (%llu)", data, data );
  		}
! 		break;
  
! 	  case DIAMETER_TIME:
! 		valstr=diameter_time_to_string(dataBuffer);
  
! 		proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 									tvb, offset, avpDataLength, dataBuffer, "Time: %s", valstr);
! 		break;
  
! 	  case DIAMETER_ENUMERATED:
! 		{
! 		  guint32 data;
! 		  
! 		  memcpy(&data, dataBuffer, 4);
! 		  data = ntohl(data);
! 		  valstr = diameter_avp_get_value(avph.avp_code, data);
! 		  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
! 									 tvb, offset, avpDataLength, data,
! 									 "Value: 0x%08x (%lu): %s", data, data, valstr);
! 		}
! 		break;
! 	  default:
! 	  case DIAMETER_OCTET_STRING:
! 		proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
! 									tvb, offset, avpDataLength, dataBuffer,
! 									"Hex Data Highlighted Below");
! 		break;
! 				
! 	  } /* switch type */
! 	} /* avpi_tree != null */
! 	offset += (avpLength - hdrLength);
! 	offset += fixAmt; /* fix byte alignment */
!   } /* loop */
! } /* dissect_avps */
! 
  
  
  void
***************
*** 780,841 ****
  {
  
  	static hf_register_info hf[] = {
- 		{ &hf_diameter_reserved,
- 		  { "Reserved", "diameter.reserved", FT_UINT8, BASE_HEX, NULL, 0x0,
- 		    "Should be zero", HFILL }},
- 		{ &hf_diameter_flags,
- 		  { "Flags", "diameter.flags", FT_UINT8, BASE_HEX, NULL, 0xf8,
- 		    "", HFILL }},
  		{ &hf_diameter_version,
! 		  { "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x07,
  		    "", HFILL }},
  		{ &hf_diameter_length,
! 		  { "Length","diameter.length", FT_UINT16, BASE_DEC, NULL, 0x0,
  		    "", HFILL }},
  		{ &hf_diameter_hopbyhopid,
  		  { "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
  		    BASE_HEX, NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_endtoendid,
  		  { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32, 
  		    BASE_HEX, NULL, 0x0, "", HFILL }},
- 		{ &hf_diameter_code,
- 		  { "Command Code","diameter.code", FT_UINT32, BASE_DEC,
- 		    VALS(diameter_command_code_vals), 0x0, "", HFILL }},
- 		{ &hf_diameter_vendor_id,
- 		  { "VendorId",	"diameter.vendorId", FT_UINT32, BASE_DEC, NULL, 0x0,
- 		    "", HFILL }},
  
  		{ &hf_diameter_avp_code,
  		  { "AVP Code","diameter.avp.code", FT_UINT32, BASE_DEC,
! 		    VALS(diameter_attrib_type_vals), 0x0, "", HFILL }},
  		{ &hf_diameter_avp_length,
! 		  { "AVP length","diameter.avp.length", FT_UINT16, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
! 		{ &hf_diameter_avp_reserved,
! 		  { "AVP Reserved","diameter.avp.reserved", FT_UINT8, BASE_HEX,
! 		    NULL, 0x0, "Should be Zero", HFILL }},
  		{ &hf_diameter_avp_flags,
  		  { "AVP Flags","diameter.avp.flags", FT_UINT8, BASE_HEX,
! 		    NULL, 0x1f, "", HFILL }},
  		{ &hf_diameter_avp_vendor_id,
  		  { "AVP Vendor Id","diameter.avp.vendorId", FT_UINT32, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_avp_data_uint32,
  		  { "AVP Data","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
- #if 0
- 		{ &hf_diameter_avp_data_uint64,
- 		  { "AVP Data","diameter.avp.data.uint64", FT_UINT64, BASE_DEC,
- 		    NULL, 0x0, "", HFILL }},
- #endif
  		{ &hf_diameter_avp_data_int32,
  		  { "AVP Data","diameter.avp.data.int32", FT_INT32, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
- #if 0
- 		{ &hf_diameter_avp_data_int64,
- 		  { "AVP Data","diameter.avp.data.int64", FT_INT_64, BASE_DEC,
- 		    NULL, 0x0, "", HFILL }},
- #endif
  		{ &hf_diameter_avp_data_bytes,
  		  { "AVP Data","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
  		    NULL, 0x0, "", HFILL }},
--- 832,935 ----
  {
  
  	static hf_register_info hf[] = {
  		{ &hf_diameter_version,
! 		  { "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x00,
  		    "", HFILL }},
  		{ &hf_diameter_length,
! 		  { "Length","diameter.length", FT_UINT24, BASE_DEC, NULL, 0x0,
! 		    "", HFILL }},
! 
! 		{ &hf_diameter_flags,
! 		  { "Flags", "diameter.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
  		    "", HFILL }},
+ 		{ &hf_diameter_flags_request,
+ 		{ "Request", "diameter.flags.request", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_R,
+ 			"", HFILL }},
+ 		{ &hf_diameter_flags_proxyable,
+ 		{ "Proxyable", "diameter.flags.proxyable", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_P,
+ 			"", HFILL }},
+ 		{ &hf_diameter_flags_error,
+ 		{ "Error","diameter.flags.error", FT_BOOLEAN, 8, TFS(&flags_set_truth), DIAM_FLAGS_E,
+ 			"", HFILL }},
+ 		{ &hf_diameter_flags_reserved3,
+ 		{ "Reserved","diameter.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set),
+ 		  DIAM_FLAGS_RESERVED3, "", HFILL }},
+ 		{ &hf_diameter_flags_reserved4,
+ 		{ "Reserved","diameter.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set),
+ 		  DIAM_FLAGS_RESERVED4, "", HFILL }},
+ 		{ &hf_diameter_flags_reserved5,
+ 		{ "Reserved","diameter.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set),
+ 		  DIAM_FLAGS_RESERVED5, "", HFILL }},
+ 		{ &hf_diameter_flags_reserved6,
+ 		{ "Reserved","diameter.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set),
+ 		  DIAM_FLAGS_RESERVED6, "", HFILL }},
+ 		{ &hf_diameter_flags_reserved7,
+ 		{ "Reserved","diameter.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set),
+ 		  DIAM_FLAGS_RESERVED7, "", HFILL }},
+ 
+ 		{ &hf_diameter_code,
+ 		  { "Command Code","diameter.code", FT_UINT24, BASE_DEC,
+ 		    NULL, 0x0, "", HFILL }},
+ 		{ &hf_diameter_vendor_id,
+ 		  { "VendorId",	"diameter.vendorId", FT_UINT32, BASE_DEC, NULL,
+ 			0x0,"", HFILL }},
  		{ &hf_diameter_hopbyhopid,
  		  { "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
  		    BASE_HEX, NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_endtoendid,
  		  { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32, 
  		    BASE_HEX, NULL, 0x0, "", HFILL }},
  
  		{ &hf_diameter_avp_code,
  		  { "AVP Code","diameter.avp.code", FT_UINT32, BASE_DEC,
! 		    NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_avp_length,
! 		  { "AVP Length","diameter.avp.length", FT_UINT24, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
! 
! 
  		{ &hf_diameter_avp_flags,
  		  { "AVP Flags","diameter.avp.flags", FT_UINT8, BASE_HEX,
! 		    NULL, 0x0, "", HFILL }},
! 		{ &hf_diameter_avp_flags_vendor_specific,
! 		{ "Vendor-Specific", "diameter.flags.vendorspecific", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_V,
! 			"", HFILL }},
! 		{ &hf_diameter_avp_flags_mandatory,
! 		{ "Mandatory", "diameter.flags.mandatory", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_M,
! 			"", HFILL }},
! 		{ &hf_diameter_avp_flags_protected,
! 		{ "Protected","diameter.avp.flags.protected", FT_BOOLEAN, 8, TFS(&flags_set_truth), AVP_FLAGS_P,
! 			"", HFILL }},
! 		{ &hf_diameter_avp_flags_reserved3,
! 		{ "Reserved","diameter.avp.flags.reserved3", FT_BOOLEAN, 8, TFS(&reserved_set),
! 		  AVP_FLAGS_RESERVED3,	"", HFILL }},
! 		{ &hf_diameter_avp_flags_reserved4,
! 		{ "Reserved","diameter.avp.flags.reserved4", FT_BOOLEAN, 8, TFS(&reserved_set),
! 		  AVP_FLAGS_RESERVED4,	"", HFILL }},
! 		{ &hf_diameter_avp_flags_reserved5,
! 		{ "Reserved","diameter.avp.flags.reserved5", FT_BOOLEAN, 8, TFS(&reserved_set),
! 		  AVP_FLAGS_RESERVED5,	"", HFILL }},
! 		{ &hf_diameter_avp_flags_reserved6,
! 		{ "Reserved","diameter.avp.flags.reserved6", FT_BOOLEAN, 8, TFS(&reserved_set),
! 		  AVP_FLAGS_RESERVED6,	"", HFILL }},
! 		{ &hf_diameter_avp_flags_reserved7,
! 		{ "Reserved","diameter.avp.flags.reserved7", FT_BOOLEAN, 8, TFS(&reserved_set),
! 		  AVP_FLAGS_RESERVED7,	"", HFILL }},
  		{ &hf_diameter_avp_vendor_id,
  		  { "AVP Vendor Id","diameter.avp.vendorId", FT_UINT32, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
+ 		{ &hf_diameter_avp_data_uint64,
+ 		  { "AVP Data","diameter.avp.data.uint64", FT_UINT32, BASE_DEC,
+ 		    NULL, 0x0, "", HFILL }},
+ 		{ &hf_diameter_avp_data_int64,
+ 		  { "AVP Data","diameter.avp.data.int64", FT_INT32, BASE_DEC,
+ 		    NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_avp_data_uint32,
  		  { "AVP Data","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_avp_data_int32,
  		  { "AVP Data","diameter.avp.data.int32", FT_INT32, BASE_DEC,
  		    NULL, 0x0, "", HFILL }},
  		{ &hf_diameter_avp_data_bytes,
  		  { "AVP Data","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
  		    NULL, 0x0, "", HFILL }},
***************
*** 856,862 ****
--- 950,958 ----
  	};
  	static gint *ett[] = {
  		&ett_diameter,
+ 		&ett_diameter_flags,
  		&ett_diameter_avp,
+ 		&ett_diameter_avp_flags,
  		&ett_diameter_avpinfo
  	};
  	module_t *diameter_module;