aboutsummaryrefslogtreecommitdiffstats
path: root/packet-diameter.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-07-30 20:08:44 +0000
committerGuy Harris <guy@alum.mit.edu>2001-07-30 20:08:44 +0000
commit76a85d57644c9a25e4b7ee0ee9504914183ffe60 (patch)
tree5ebf64f196279f6d53d8ce52c8e7408bcb9bc42b /packet-diameter.c
parent2997acf2ccc4064ac152980eaf73bdceb5da11f6 (diff)
From David Frascone: update to the DIAMETER dissector for
draft-ietf-aaa-diameter-07. His changenotes: 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. svn path=/trunk/; revision=3799
Diffstat (limited to 'packet-diameter.c')
-rw-r--r--packet-diameter.c1302
1 files changed, 699 insertions, 603 deletions
diff --git a/packet-diameter.c b/packet-diameter.c
index 4891518e74..a77d31fe7c 100644
--- a/packet-diameter.c
+++ b/packet-diameter.c
@@ -1,7 +1,7 @@
/* packet-diameter.c
* Routines for DIAMETER packet disassembly
*
- * $Id: packet-diameter.c,v 1.24 2001/07/15 19:14:00 guy Exp $
+ * $Id: packet-diameter.c,v 1.25 2001/07/30 20:08:44 guy Exp $
*
* Copyright (c) 2001 by David Frascone <dave@frascone.com>
*
@@ -47,26 +47,37 @@
#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;
+ /* 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,29 +86,52 @@ typedef enum {
#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_flags = -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;
-#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;
@@ -105,7 +139,9 @@ static int hf_diameter_avp_data_v6addr = -1;
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,44 +149,125 @@ static int gbl_diameterTcpPort=TCP_PORT_DIAMETER;
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;
+ guint32 versionLength;
+ guint32 flagsCmdCode;
+ guint32 vendorId;
+ guint32 hopByHopId;
+ guint32 endToEndId;
} e_diameterhdr;
typedef struct _e_avphdr {
- guint32 avp_code;
- guint16 avp_length;
- guint8 avp_reserved;
- guint8 avp_flags;
- guint32 avp_vendorId; /* optional */
+ 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_I 0x10
-#define DIAM_FLAGS_R 0x08
-#define DIAM_FLAGS_RESERVED 0xc0 /* 11000000 -- X X E I R V V V */
+#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 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 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 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);
+
+
+
+
+/* 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,149 +277,190 @@ static gchar *DetermineMessageType(char flagsVer);
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;
+ /* 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);
+ /* 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));
+ /* 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";
- }
+ /* 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");
+ }
- /* 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;
+ /* 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 (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);
+ if (strlen(flagstr) == 0) {
+ strcpy(flagstr,"<None>");
}
-
-
-/* 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;
+ }
+
+ /* 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;
+ }
- /* Command Code */
- proto_tree_add_uint(diameter_tree, hf_diameter_code,
- tvb, offset, 4, dh.commandCode);
- offset += 4;
+ /* 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;
+ }
- /* Vendor Id */
- proto_tree_add_uint(diameter_tree,hf_diameter_vendor_id,
- tvb, offset, 4,
- dh.vendorId);
- offset += 4;
+ 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);
+ }
+
- /* If we have a bad packet, don't bother trying to parse the AVPs */
- if (BadPacket) {
- return;
- }
+ /* 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 */
+ /* Start looking at the AVPS */
+ /* Make the next tvbuff */
- /* Update the lengths */
- avplength= dh.pktLength - sizeof(e_diameterhdr);
+ /* 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_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);
- }
+ avp_tree = proto_item_add_subtree(avptf,
+ ett_diameter_avp);
+ if (avp_tree != NULL) {
+ dissect_avps( avp_tvb, pinfo, avp_tree);
}
+ }
} /* dissect_diameter */
/*
@@ -311,439 +469,333 @@ static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
*/
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;
+ /* 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;
- size_t packetLength;
- size_t avpDataLength;
- int avpType;
+ 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;
+ }
- packetLength = tvb_length(tvb);
+ /* Spin around until we run out of packet */
+ while (packetLength > 0 ) {
- /* 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;
+ /* 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;
}
-
- /* 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, 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>");
+ }
+ }
- /* 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 (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;
+ }
- /* 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);
- }
+ if (vendorId) {
+ strcpy(vendorString,
+ val_to_str(vendorId, diameter_vendor_specific_vendors, "Unknown Vendor: %08x"));
+ } else {
+ vendorString[0]='\0';
+ }
- /* 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 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 (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;
- }
+ /* 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;
+ }
- /*
- * 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)",
+ /*
+ * 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;
- }
+ 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;
+ /* 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;
- 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);
+ 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;
+ }
- 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;
+ 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);
- }
- offset += avph.avp_length - hdrLength;
- }
- offset += fixAmt; /* fix byte alignment */
- }
-} /* dissect_avps */
+ group_tree = proto_item_add_subtree(grouptf,
+ ett_diameter_avp);
-/* 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);
+ 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_ATT_LOGIN_SERVICE:
- return rd_match_strval(value, diameter_login_service_vals);
+
+ 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_ATT_RSVP_SERVICE_TYPE:
- return rd_match_strval(value, diameter_rsvp_service_type_vals);
+ 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_ATT_ACCT_STATUS_TYPE:
- return rd_match_strval(value, diameter_acct_status_type_vals);
+ 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;
- }
-
- 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:
{
- 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:
+ 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 );
+ }
+ break;
+
+ case DIAMETER_UNSIGNED32:
{
- gint64 llval;
- llval = pntohll(input);
- sprintf(buffer,"%lld", llval);
+ 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%08x (%u)", data,
+ data );
}
- break;
- case DIAMETER_UNSIGNED64:
+ break;
+
+ case DIAMETER_INTEGER64:
{
- guint64 llval;
- llval = pntohll(input);
- sprintf(buffer,"%llu", llval);
+ 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;
-#endif
- case DIAMETER_TIME:
+ break;
+ case DIAMETER_UNSIGNED64:
{
- 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);
- }
+ 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 );
}
- default:
- /* Do nothing */
- ;
+ 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 (%u): %s", data, data, valstr);
}
- return buffer;
-} /* rd value to str */
+ 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 */
-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
@@ -780,62 +832,104 @@ proto_register_diameter(void)
{
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,
+ { "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x00,
"", HFILL }},
{ &hf_diameter_length,
- { "Length","diameter.length", FT_UINT16, BASE_DEC, NULL, 0x0,
+ { "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_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 }},
+ NULL, 0x0, "", HFILL }},
{ &hf_diameter_avp_length,
- { "AVP length","diameter.avp.length", FT_UINT16, BASE_DEC,
+ { "AVP Length","diameter.avp.length", FT_UINT24, 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 }},
+ 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 }},
-#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 }},
@@ -856,7 +950,9 @@ proto_register_diameter(void)
};
static gint *ett[] = {
&ett_diameter,
+ &ett_diameter_flags,
&ett_diameter_avp,
+ &ett_diameter_avp_flags,
&ett_diameter_avpinfo
};
module_t *diameter_module;