From Martin Regner: fix dissection of non-standard parameters.
[obnox/wireshark/wip.git] / packet-diameter.c
index 36dce6aa9816deeb637e6ee36b7e6d7b28b50a89..afcaf8cf0f91e036a447f057f36f1d3f2d31ab24 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-diameter.c
  * Routines for Diameter packet disassembly
  *
- * $Id: packet-diameter.c,v 1.43 2002/01/30 23:08:26 guy Exp $
+ * $Id: packet-diameter.c,v 1.55 2003/07/09 05:37:47 tpot Exp $
  *
  * Copyright (c) 2001 by David Frascone <dave@frascone.com>
  *
 #include "config.h"
 #endif
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -78,7 +70,7 @@ typedef enum {
   DIAMETER_MIP_REG_REQ,        /* OctetString */
   DIAMETER_VENDOR_ID,           /* Integer32  */
   DIAMETER_APPLICATION_ID
-  
+
 } diameterDataType;
 
 
@@ -160,11 +152,6 @@ static ApplicationId   *ApplicationIdHead=NULL;
 #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"
@@ -174,7 +161,6 @@ 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;
@@ -189,7 +175,6 @@ 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;
@@ -218,15 +203,13 @@ static gint ett_diameter_avp = -1;
 static gint ett_diameter_avp_flags = -1;
 static gint ett_diameter_avpinfo = -1;
 
-static char gbl_diameterString[200];
 static int gbl_diameterTcpPort=TCP_PORT_DIAMETER;
 static int gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
 
 /* desegmentation of Diameter over TCP */
 static gboolean gbl_diameter_desegment = TRUE;
 
-#define DIAMETER_DIR "diameter"
-#define DICT_FN "dictionary.xml"
+#define DICT_FN  "diameter/dictionary.xml"
 static gchar *gbl_diameterDictionary = NULL;
 
 typedef struct _e_diameterhdr {
@@ -292,10 +275,10 @@ xmlParseFilePush( char *filename, int checkValid) {
   int res, size = 1024;
   char chars[1024];
   xmlParserCtxtPtr ctxt;
-       
+
   /* I wonder what kind of a performance hit this is? */
   *XmlStub.xmlDoValidityCheckingDefaultValue = checkValid;
-  
+
   f = fopen(filename, "r");
   if (f == NULL) {
        g_warning("Diameter: Unable to open %s", filename);
@@ -314,7 +297,7 @@ xmlParseFilePush( char *filename, int checkValid) {
        valid=ctxt->valid;
        XmlStub.xmlFreeParserCtxt(ctxt);
   }
-  fclose(f); 
+  fclose(f);
 
   /* Check valid */
   if (!valid) {
@@ -340,7 +323,7 @@ addStaticAVP(int code, gchar *name, diameterDataType type, value_string *values)
   if (values) {
        for (i=0; values[i].strptr != NULL; i++) {
          ValueName *ve = NULL;
-                       
+
          ve = g_malloc(sizeof(ValueName));
          ve->name = strdup(values[i].strptr);
          ve->value = values[i].value;
@@ -364,7 +347,7 @@ addStaticAVP(int code, gchar *name, diameterDataType type, value_string *values)
   avpListHead = entry;
 
   return (0);
-       
+
 } /* addStaticAVP */
 
 /*
@@ -373,7 +356,7 @@ addStaticAVP(int code, gchar *name, diameterDataType type, value_string *values)
  * add them too.
  */
 static int
-xmlParseAVP(xmlDocPtr doc, xmlNodePtr cur)
+xmlParseAVP(xmlNodePtr cur)
 {
   char *name=NULL, *description=NULL, *code=NULL, *mayEncrypt=NULL,
        *mandatory=NULL, *protected=NULL, *vendorBit=NULL, *vendorName = NULL,
@@ -398,28 +381,26 @@ xmlParseAVP(xmlDocPtr doc, xmlNodePtr cur)
   cur = cur->xmlChildrenNode;
 
   while (cur != NULL ) {
-       if (!strcasecmp((char *)cur->name, "type")) {
+       if (strcasecmp(cur->name, "type") == 0) {
          type = XmlStub.xmlGetProp(cur, "type-name");
-       }
-       if (!strcasecmp((char *)cur->name, "enum")) {
+       } else if (strcasecmp(cur->name, "enum") == 0) {
          char *valueName=NULL, *valueCode=NULL;
          ValueName *ve = NULL;
          valueName = XmlStub.xmlGetProp(cur, "name");
          valueCode = XmlStub.xmlGetProp(cur, "code");
-                       
+
          if (!valueName || !valueCode) {
                g_warning( "Error, bad value on avp %s", name);
                return (-1);
          }
-                       
+
          ve = g_malloc(sizeof(ValueName));
          ve->name = strdup(valueName);
          ve->value = atol(valueCode);
 
          ve->next = vEntry;
          vEntry = ve;
-       }
-       if (!strcasecmp((char *)cur->name, "grouped")) {
+       } else if (strcasecmp(cur->name, "grouped") == 0) {
          /* WORK Recurse here for grouped AVPs */
          type = "grouped";
        }
@@ -448,13 +429,13 @@ xmlParseAVP(xmlDocPtr doc, xmlNodePtr cur)
   }
 
   /* WORK - Handle flags  -- for validation later */
-       
+
 
   /* And, create the entry */
   entry = (avpInfo *)g_malloc(sizeof(avpInfo));
   entry->name = g_strdup(name);
   entry->code = atol(code);
-  if (vendorName) 
+  if (vendorName)
        entry->vendorName = g_strdup(vendorName);
   else
        entry->vendorName = NULL;
@@ -511,7 +492,7 @@ addCommand(int code, char *name, char *vendorId)
  * list of commands.
  */
 static int
-xmlParseCommand(xmlDocPtr doc, xmlNodePtr cur)
+xmlParseCommand(xmlNodePtr cur)
 {
   char *name, *code, *vendorIdString;
 
@@ -550,10 +531,10 @@ dictionaryAddApplication(char *name, int id)
        g_warning( "Unable to allocate memory");
        return (-1);
   }
-       
+
   entry->name = g_strdup(name);
   entry->id = id;
-       
+
   /* Add it to the list */
   entry->next = ApplicationIdHead;
   ApplicationIdHead = entry;
@@ -588,7 +569,7 @@ addVendor(int id, gchar *name, gchar *longName)
  * This routine will pars in a XML vendor entry.
  */
 static int
-xmlParseVendor(xmlDocPtr doc, xmlNodePtr cur)
+xmlParseVendor(xmlNodePtr cur)
 {
   char *name=NULL, *code=NULL, *id=NULL;
 
@@ -609,23 +590,23 @@ xmlParseVendor(xmlDocPtr doc, xmlNodePtr cur)
  * This routine will either parse in the base protocol, or an application.
  */
 static int
-xmlDictionaryParseSegment(xmlDocPtr doc, xmlNodePtr cur, int base)
+xmlDictionaryParseSegment(xmlNodePtr cur, int base)
 {
   if (!base) {
        char *name;
        char *id;
-               
+
        /* Add our application */
        id = XmlStub.xmlGetProp(cur, "id");
        name = XmlStub.xmlGetProp(cur, "name");
-               
+
        if (!name || !id) {
          /* ERROR!!! */
          g_warning("Diameter: Invalid application!: name=\"%s\", id=\"%s\"",
                                name?name:"NULL", id?id:"NULL");
          return -1;
        }
-               
+
        /* Add the application */
        if (dictionaryAddApplication(name, atol(id)) != 0) {
          /* ERROR! */
@@ -633,25 +614,25 @@ xmlDictionaryParseSegment(xmlDocPtr doc, xmlNodePtr cur, int base)
        }
   }
 
-       
+
   /*
    * Get segment values
    */
   cur = cur->xmlChildrenNode;
   while (cur != NULL) {
-       if (!strcasecmp((char *)cur->name, "avp")) {
+       if (strcasecmp(cur->name, "avp") == 0) {
          /* we have an avp!!! */
-         xmlParseAVP(doc, cur);
-       } else if (!strcasecmp((char *)cur->name, "vendor")) {
+         xmlParseAVP(cur);
+       } else if (strcasecmp(cur->name, "vendor") == 0) {
          /* we have a vendor */
-         xmlParseVendor(doc, cur);
+         xmlParseVendor(cur);
          /* For now, ignore typedefn and text */
-       } else if (!strcasecmp((char *)cur->name, "command")) {
+       } else if (strcasecmp(cur->name, "command") == 0) {
          /* Found a command */
-         xmlParseCommand(doc,cur);
-       } else if (!strcasecmp((char *)cur->name, "text")) {
-       } else if (!strcasecmp((char *)cur->name, "comment")) {
-       } else if (!strcasecmp((char *)cur->name, "typedefn")) {
+         xmlParseCommand(cur);
+       } else if (strcasecmp(cur->name, "text") == 0) {
+       } else if (strcasecmp(cur->name, "comment") == 0) {
+       } else if (strcasecmp(cur->name, "typedefn") == 0) {
          /* WORK -- parse in valid types . . . */
        } else {
          /* IF we got here, we're an error */
@@ -665,21 +646,21 @@ xmlDictionaryParseSegment(xmlDocPtr doc, xmlNodePtr cur, int base)
 } /* xmlDictionaryParseSegment */
 
 /*
- * The main xml parse routine.  This will walk through an XML 
+ * The main xml parse routine.  This will walk through an XML
  * dictionary that has been parsed by libxml.
  */
 static int
-xmlDictionaryParse(xmlDocPtr doc, xmlNodePtr cur)
+xmlDictionaryParse(xmlNodePtr cur)
 {
   /* We should expect a base protocol, followed by multiple applicaitons */
   while (cur != NULL) {
-       if (!strcasecmp((char *)cur->name, "base")) {
+       if (strcasecmp(cur->name, "base") == 0) {
          /* Base protocol.  Descend and parse */
-         xmlDictionaryParseSegment(doc, cur, 1);
-       } else if (!strcasecmp((char *)cur->name, "application")) {
+         xmlDictionaryParseSegment(cur, 1);
+       } else if (strcasecmp(cur->name, "application") == 0) {
          /* Application.  Descend and parse */
-         xmlDictionaryParseSegment(doc, cur, 0);
-       } else if (!strcasecmp((char *)cur->name, "text")) {
+         xmlDictionaryParseSegment(cur, 0);
+       } else if (strcasecmp(cur->name, "text") == 0) {
          /* Ignore text */
        } else {
          g_warning( "Diameter: XML Expecting a base or an application  (got \"%s\")",
@@ -715,7 +696,7 @@ loadXMLDictionary()
                          gbl_diameterDictionary);
        return -1;
   }
-       
+
   /*
    * Check the document is of the right kind
    */
@@ -732,12 +713,12 @@ loadXMLDictionary()
        XmlStub.xmlFreeDoc(doc);
        return -1;
   }
-       
+
   /*
    * Ok, the dictionary has been parsed by libxml, and is valid.
    * All we have to do now is read in our information.
    */
-  if (xmlDictionaryParse(doc, cur->xmlChildrenNode) != 0) {
+  if (xmlDictionaryParse(cur->xmlChildrenNode) != 0) {
        /* Error has already been printed */
        return -1;
   }
@@ -781,8 +762,8 @@ initializeDictionaryDefaults()
 
 } /* initializeDictionaryDefaults */
 
-/* 
- * This routine will attempt to load the XML dictionary, and on 
+/*
+ * This routine will attempt to load the XML dictionary, and on
  * failure, will call initializeDictionaryDefaults to load in
  * our static dictionary.
  */
@@ -790,7 +771,7 @@ static void
 initializeDictionary()
 {
   /*
-   * Using ugly ordering here.  If loadLibXML succeeds, then 
+   * Using ugly ordering here.  If loadLibXML succeeds, then
    * loadXMLDictionary will be called.  This is one of the few times when
    * I think this is prettier than the nested if alternative.
    */
@@ -858,8 +839,8 @@ diameter_command_to_str(guint32 commandCode, guint32 vendorId)
          }
        }
   }
-  
-  g_warning("Diameter: Unable to find name for command code 0x%08x, Vendor \"%u\"!", 
+
+  g_warning("Diameter: Unable to find name for command code 0x%08x, Vendor \"%u\"!",
                        commandCode, vendorId);
   snprintf(buffer, sizeof(buffer),
                   "Cmd-0x%08x", commandCode);
@@ -884,17 +865,17 @@ diameter_app_to_str(guint32 vendorId) {
 } /*diameter_app_to_str */
 
 /* return an avp type, based on the code */
-diameterDataType
+static diameterDataType
 diameter_avp_get_type(guint32 avpCode, guint32 vendorId){
   avpInfo *probe;
   gchar *vendorName=NULL;
-  
+
   if (vendorId)
        vendorName = diameter_vendor_to_str(vendorId, FALSE);
-  
+
   for (probe=avpListHead; probe; probe=probe->next) {
        if (avpCode == probe->code) {
-         
+
          if (vendorId) {
 /*             g_warning("AvpType: Comparing \"%s\" to \"%s\"", */
 /*                               vendorName?vendorName:"(null)", */
@@ -911,7 +892,7 @@ diameter_avp_get_type(guint32 avpCode, guint32 vendorId){
          }
        }
   }
-       
+
   /* If we don't find it, assume it's data */
   g_warning("Diameter: Unable to find type for avpCode %u, Vendor %u!", avpCode,
                        vendorId);
@@ -948,7 +929,7 @@ diameter_avp_get_name(guint32 avpCode, guint32 vendorId)
        }
   }
 
-  g_warning("Diameter: Unable to find name for AVP 0x%08x, Vendor %u!", 
+  g_warning("Diameter: Unable to find name for AVP 0x%08x, Vendor %u!",
                        avpCode, vendorId);
 
   /* If we don't find it, build a name string */
@@ -1002,21 +983,6 @@ diameter_avp_get_value(guint32 avpCode, guint32 vendorId, guint32 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(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 */
 
@@ -1060,25 +1026,25 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
          initializeDictionary();
          initialized=TRUE;
   }
-       
+
   /* Make entries in Protocol column and Info column on summary display */
-  if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
+  if (check_col(pinfo->cinfo, COL_PROTOCOL))
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Diameter");
-  if (check_col(pinfo->cinfo, COL_INFO)) 
+  if (check_col(pinfo->cinfo, COL_INFO))
        col_clear(pinfo->cinfo, 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);
+  dh.versionLength = g_ntohl(dh.versionLength);
+  dh.flagsCmdCode = g_ntohl(dh.flagsCmdCode);
+  dh.vendorId = g_ntohl(dh.vendorId);
+  dh.hopByHopId = g_ntohl(dh.hopByHopId);
+  dh.endToEndId = g_ntohl(dh.endToEndId);
 
   if (dh.vendorId) {
-       strcpy(vendorName, 
+       strcpy(vendorName,
                   diameter_vendor_to_str(dh.vendorId, TRUE));
   } else {
        strcpy(vendorName, "None");
@@ -1092,7 +1058,7 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
   commandCode = DIAM_GET_COMMAND(dh);
 
   /* Set up our flags */
-  if (check_col(pinfo->cinfo, COL_INFO) || tree) {  
+  if (check_col(pinfo->cinfo, COL_INFO) || tree) {
        flagstr[0]=0;
        for (i = 0; i < 8; i++) {
          bpos = 1 << i;
@@ -1107,10 +1073,10 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
          strcpy(flagstr,"<None>");
        }
   }
-  
+
   /* Set up our commandString */
   strcpy(commandString, diameter_command_to_str(commandCode, dh.vendorId));
-  if (flags & DIAM_FLAGS_R) 
+  if (flags & DIAM_FLAGS_R)
        strcat(commandString, "-Request");
   else
        strcat(commandString, "-Answer");
@@ -1145,7 +1111,7 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
                                 (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. */
@@ -1216,12 +1182,12 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
 
        /* Update the lengths */
        avplength= pktLength - sizeof(e_diameterhdr);
-    
+
        avp_tvb = tvb_new_subset(tvb, offset, avplength, avplength);
        avptf = proto_tree_add_text(diameter_tree,
                                                                tvb, offset, avplength,
                                                                "Attribute Value Pairs");
-               
+
        avp_tree = proto_item_add_subtree(avptf,
                                                                          ett_diameter_avp);
        if (avp_tree != NULL) {
@@ -1246,7 +1212,7 @@ dissect_diameter_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        guint32 plen;
        guint32 available_bytes;
 /*     guint32 noffset; */
-       
+
        /* Loop through the packet, dissecting multiple diameter messages */
        do {
                available_bytes = tvb_length_remaining(tvb, offset);
@@ -1271,7 +1237,7 @@ dissect_diameter_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                                return;
                        }
                }
-       
+
                /* Otherwise, dissect our packet */
                offset = dissect_diameter_common(tvb, offset, pinfo, tree);
 
@@ -1309,7 +1275,7 @@ safe_dissect_mip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
   mip_tvb = tvb_new_subset(tvb, offset,
                                                   MIN(length, tvb_length(tvb)-offset),
                                                   length);
-       
+
   /* The contained packet is a MIP registration request;
         dissect it with the MIP dissector. */
   col_set_writable(pinfo->cinfo, FALSE);
@@ -1356,8 +1322,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
   int hdrLength;
   int fixAmt;
   proto_tree *avpi_tree;
-  size_t offset = 0 ;
-  char dataBuffer[4096];
+  size_t offset = 0;
   tvbuff_t        *group_tvb;
   proto_tree *group_tree;
   proto_item *grouptf;
@@ -1368,7 +1333,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
   guint8 flags;
   proto_item      *tf;
   proto_tree      *flags_tree;
-       
+
   gint32 packetLength;
   size_t avpDataLength;
   int avpType;
@@ -1397,19 +1362,19 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
          /* 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);
-       
+       avph.avp_code = g_ntohl(avph.avp_code);
+       avph.avp_flagsLength = g_ntohl(avph.avp_flagsLength);
+
        flags = (avph.avp_flagsLength & 0xff000000) >> 24;
        avpLength = avph.avp_flagsLength & 0x00ffffff;
-       
+
        /* Set up our flags string */
-       if (check_col(pinfo->cinfo, COL_INFO) || avp_tree) {  
+       if (check_col(pinfo->cinfo, COL_INFO) || avp_tree) {
          flagstr[0]=0;
          for (i = 0; i < 8; i++) {
                bpos = 1 << i;
@@ -1427,25 +1392,25 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
 
        /* Dissect our vendor id if it exists  and set hdr length */
        if (flags & AVP_FLAGS_V) {
-         vendorId = ntohl(avph.avp_vendorId);
+         vendorId = g_ntohl(avph.avp_vendorId);
          /* Vendor id */
          hdrLength = sizeof(e_avphdr);
        } else {
          /* No vendor */
-         hdrLength = sizeof(e_avphdr) - 
+         hdrLength = sizeof(e_avphdr) -
                sizeof(guint32);
          vendorId = 0;
        }
 
        if (vendorId) {
-         strcpy(vendorName, 
+         strcpy(vendorName,
                         diameter_vendor_to_str(vendorId, TRUE));
        } else {
          vendorName[0]='\0';
        }
 
        /* Check for bad length */
-       if (avpLength < MIN_AVP_SIZE || 
+       if (avpLength < MIN_AVP_SIZE ||
                ((long)avpLength > packetLength)) {
          g_warning("Diameter: AVP payload size invalid: avp_length: %ld bytes,  "
                                "min: %ld bytes,    packetLen: %d",
@@ -1462,17 +1427,17 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
          /* 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) ",
@@ -1482,7 +1447,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
 
        /* Make avp Name & type */
        strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code,vendorId),
-                                                                        TypeValues, 
+                                                                        TypeValues,
                                                                         "Unknown-Type: 0x%08x"));
        strcpy(avpNameString, diameter_avp_get_name(avph.avp_code, vendorId));
 
@@ -1499,7 +1464,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
          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);
@@ -1533,15 +1498,14 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
          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)");
+                                       tvb, offset, tvb_length(tvb) - offset,
+                                       tvb_get_ptr(tvb, offset, tvb_length(tvb) - offset),
+                                       "Bad AVP (Suspect Data Not Dissected)");
                return;
          }
 
          avpType=diameter_avp_get_type(avph.avp_code,vendorId);
-         tvb_memcpy(tvb, (guint8*) dataBuffer, offset, MIN(4095,avpDataLength));
-       
-         
+
          switch(avpType) {
          case DIAMETER_GROUPED:
                sprintf(buffer, "%s Grouped AVPs", avpNameString);
@@ -1549,7 +1513,7 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
                grouptf = proto_tree_add_text(avpi_tree,
                                                                          tvb, offset, tvb_length(tvb),
                                                                          buffer);
-                               
+
                group_tree = proto_item_add_subtree(grouptf,
                                                                                        ett_diameter_avp);
 
@@ -1561,115 +1525,170 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_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);
+               {
+                 const guint8 *data;
+
+                 data = tvb_get_ptr(tvb, offset, avpDataLength);
+                 proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
+                                              tvb, offset, avpDataLength, data,
+                                              "Identity: %*.*s",
+                                              (int)avpDataLength,
+                                              (int)avpDataLength, data);
+               }
                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);
+               {
+                 const guint8 *data;
+
+                 data = tvb_get_ptr(tvb, offset, avpDataLength);
+                 proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
+                                              tvb, offset, avpDataLength, data,
+                                              "UTF8String: %*.*s",
+                                              (int)avpDataLength,
+                                              (int)avpDataLength, data);
+               }
                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));
+                 proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
+                                     tvb, offset, avpDataLength, FALSE);
                } 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]));
+                 proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v6addr,
+                                     tvb, offset, avpDataLength, FALSE);
                } else {
                  proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
-                                                                         tvb, offset, avpDataLength, dataBuffer,
-                                                                         "Error!  Bad Address Length");
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "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: %d", data );
+               if (avpDataLength == 4) {
+                 proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int32,
+                                     tvb, offset, avpDataLength, FALSE);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Integer32 Length");
                }
                break;
 
          case DIAMETER_UNSIGNED32:
-               {
+               if (avpDataLength == 4) {
                  guint32 data;
 
-                 memcpy(&data, dataBuffer, 4);
-                 data=ntohl(data);
+                 data = tvb_get_ntohl(tvb, offset);
                  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
-                                                                        tvb, offset, avpDataLength, data,
-                                                                        "Value: 0x%08x (%u)", data,
-                                                                        data );
+                                            tvb, offset, avpDataLength, data,
+                                            "Value: 0x%08x (%u)", data, data);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Unsigned32 Length");
                }
                break;
 
          case DIAMETER_INTEGER64:
-               proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64, tvb, offset, 8, FALSE);
+               if (avpDataLength == 8) {
+                 proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64,
+                                     tvb, offset, 8, FALSE);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Integer64 Length");
+               }
                break;
 
          case DIAMETER_UNSIGNED64:
-               proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64, tvb, offset, 8, FALSE);
+               if (avpDataLength == 8) {
+                 proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64,
+                                     tvb, offset, 8, FALSE);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Unsigned64 Length");
+               }
                break;
 
          case DIAMETER_TIME:
-               valstr=diameter_time_to_string(dataBuffer);
+               if (avpDataLength == 4) {
+                 nstime_t data;
+                 gchar buffer[64];
+                 struct tm *ltp;
 
-               proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
-                                                                       tvb, offset, avpDataLength, dataBuffer, "Time: %s", valstr);
+                 data.secs = tvb_get_ntohl(tvb, offset);
+                 data.secs -= NTP_TIME_DIFF;
+                 data.nsecs = 0;
+
+                 ltp = localtime(&data.secs);
+                 strftime(buffer, 64,
+                          "%a, %d %b %Y %H:%M:%S %z", ltp);
+
+                 proto_tree_add_time_format(avpi_tree, hf_diameter_avp_data_time,
+                                            tvb, offset, avpDataLength, &data,
+                                            "Time: %s", buffer);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Time Length");
+               }
                break;
 
          case DIAMETER_ENUMERATED:
-               {
+               if (avpDataLength == 4) {
                  guint32 data;
-                 
-                 memcpy(&data, dataBuffer, 4);
-                 data = ntohl(data);
+
+                 data = tvb_get_ntohl(tvb, offset);
                  valstr = diameter_avp_get_value(avph.avp_code, vendorId, data);
                  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
-                                                                        tvb, offset, avpDataLength, data,
-                                                                        "Value: 0x%08x (%u): %s", data, data, valstr);
+                                            tvb, offset, avpDataLength, data,
+                                            "Value: 0x%08x (%u): %s", data,
+                                            data, valstr);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Enumerated Length");
                }
                break;
          case DIAMETER_VENDOR_ID:
-               {
+               if (avpDataLength == 4) {
                  guint32 data;
-                 
-                 memcpy(&data, dataBuffer, 4);
-                 data = ntohl(data);
+
+                 data = tvb_get_ntohl(tvb, offset);
                  valstr = diameter_vendor_to_str(data, TRUE);
                  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
-                                                                        tvb, offset, avpDataLength, data,
-                                                                        "%s (0x%08x)", valstr, data);
+                                            tvb, offset, avpDataLength, data,
+                                            "Vendor ID: %s (0x%08x)", valstr,
+                                            data);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Vendor ID Length");
                }
                break;
          case DIAMETER_APPLICATION_ID:
-               {
+               if (avpDataLength == 4) {
                  guint32 data;
-                 
-                 memcpy(&data, dataBuffer, 4);
-                 data = ntohl(data);
+
+                 data = tvb_get_ntohl(tvb, offset);
                  valstr = diameter_app_to_str(data);
                  proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
-                                                                        tvb, offset, avpDataLength, data,
-                                                                        "%s (0x%08x)", valstr, data);
+                                            tvb, offset, avpDataLength, data,
+                                            "Application ID: %s (0x%08x)",
+                                            valstr, data);
+               } else {
+                 proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+                                             tvb, offset, avpDataLength,
+                                             tvb_get_ptr(tvb, offset, avpDataLength),
+                                             "Error!  Bad Application ID Length");
                }
                break;
          case DIAMETER_MIP_REG_REQ:
@@ -1679,10 +1698,11 @@ static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree
          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");
+                                           tvb, offset, avpDataLength,
+                                           tvb_get_ptr(tvb, offset, avpDataLength),
+                                          "Hex Data Highlighted Below");
                break;
-                               
+
          } /* switch type */
        } /* avpi_tree != null */
        offset += (avpLength - hdrLength);
@@ -1716,8 +1736,6 @@ proto_reg_handoff_diameter(void)
   TcpPort=gbl_diameterTcpPort;
   SctpPort=gbl_diameterSctpPort;
 
-  strcpy(gbl_diameterString, "Diameter Protocol");
-
   /* g_warning ("Diameter: Adding tcp dissector to port %d",
         gbl_diameterTcpPort); */
   dissector_add("tcp.port", gbl_diameterTcpPort, diameter_tcp_handle);
@@ -1735,7 +1753,7 @@ proto_register_diameter(void)
                { &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 }},
@@ -1774,9 +1792,9 @@ proto_register_diameter(void)
                  { "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
                    BASE_HEX, NULL, 0x0, "", HFILL }},
                { &hf_diameter_endtoendid,
-                 { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32, 
+                 { "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 }},
@@ -1816,32 +1834,31 @@ proto_register_diameter(void)
                  { "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_UINT64, BASE_DEC,
+                 { "Value","diameter.avp.data.uint64", FT_UINT64, BASE_DEC,
                    NULL, 0x0, "", HFILL }},
                { &hf_diameter_avp_data_int64,
-                 { "AVP Data","diameter.avp.data.int64", FT_INT64, BASE_DEC,
+                 { "Value","diameter.avp.data.int64", FT_INT64, BASE_DEC,
                    NULL, 0x0, "", HFILL }},
                { &hf_diameter_avp_data_uint32,
-                 { "AVP Data","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
+                 { "Value","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,
+                 { "Value","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,
+                 { "Value","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
                    NULL, 0x0, "", HFILL }},
-               
                { &hf_diameter_avp_data_string,
-                 { "AVP Data","diameter.avp.data.string", FT_STRING, BASE_NONE,
+                 { "Value","diameter.avp.data.string", FT_STRING, BASE_NONE,
                    NULL, 0x0, "", HFILL }},
                { &hf_diameter_avp_data_v4addr,
-                 { "AVP Data","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
+                 { "IPv4 Address","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
                    NULL, 0x0, "", HFILL }},
                { &hf_diameter_avp_data_v6addr,
-                 { "AVP Data","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
+                 { "IPv6 Address","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
                    NULL, 0x0, "", HFILL }},
                { &hf_diameter_avp_data_time,
-                 { "AVP Data","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
+                 { "Time","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
                    NULL, 0x0, "", HFILL }},
 
        };
@@ -1854,8 +1871,7 @@ proto_register_diameter(void)
        };
        module_t *diameter_module;
 
-       proto_diameter = proto_register_protocol (gbl_diameterString,
-                                                                                         "Diameter", "diameter");
+       proto_diameter = proto_register_protocol ("Diameter Protocol", "Diameter", "diameter");
        proto_register_field_array(proto_diameter, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
@@ -1875,12 +1891,8 @@ proto_register_diameter(void)
        /*
         * Build our default dictionary filename
         */
-       if (! gbl_diameterDictionary) {
-               gbl_diameterDictionary = (gchar *) g_malloc(strlen(get_datafile_dir()) +
-                                                                                                       1 + strlen(DICT_FN) + 1); /* slash + fn + null */
-               sprintf(gbl_diameterDictionary, "%s" G_DIR_SEPARATOR_S "%s",
-                               get_datafile_dir(), DICT_FN );
-       }
+       if (! gbl_diameterDictionary)
+               gbl_diameterDictionary = get_datafile_path(DICT_FN);
        /* Now register its preferences so it can be changed. */
        prefs_register_string_preference(diameter_module, "dictionary.name",
                                                                         "Diameter XML Dictionary",