aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2006-07-03 21:18:36 +0000
committerAnders Broman <anders.broman@ericsson.com>2006-07-03 21:18:36 +0000
commit2032e960d742f358b6aa38da07180bf3fd1af00e (patch)
tree5a74cb4875fcf66a59de0d3ca1cc14c9a5edf6d4
parent2a5e5f26a1b5443bf77c7f5913b85fbb43441d82 (diff)
From Martin Mathieson:
packet-diameter.c -------------------------- I completely reindented dissect_avps() before I made any changes, but when ignoring white space (in tkdiff, -w plus checking 'Ignore blanks when diffing'), its easy to see the small changes I've made: - when fail to find AVP info, show code in tree parent in decimal (as specs do) - add an expert info (undecoded, note) to indicate unknown AVP codes diameter/imscxdx.xml ------------------------------- - added 'Associated-Identities' svn path=/trunk/; revision=18641
-rw-r--r--diameter/imscxdx.xml16
-rw-r--r--epan/dissectors/packet-diameter.c930
2 files changed, 484 insertions, 462 deletions
diff --git a/diameter/imscxdx.xml b/diameter/imscxdx.xml
index 28e67ee76b..535f7e56ff 100644
--- a/diameter/imscxdx.xml
+++ b/diameter/imscxdx.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- $Id:$ -->
+<!-- $Id$ -->
<application id="16777215" name="IMS_Cx_Dx" uri="http://www.3GPP.org/ftp/Specs/html-info/29229.htm">
@@ -277,21 +277,21 @@
<enum name="Unregistered-Profile" code="2"/>
</avp>
<!-- GROUPED -->
- <avp name="Supported-Features" code="628" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="yes">
+ <avp name="Supported-Features" code="628" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="no">
<grouped>
<gavp name="Vendor-ID"/>
<gavp name="Feature-List-ID"/>
<gavp name="Feature-List"/>
</grouped>
</avp>
- <avp name="Feature-List-ID" code="629" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="yes">
+ <avp name="Feature-List-ID" code="629" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="no">
<type type-name="Unsigned32"/>
</avp>
- <avp name="Feature-List" code="630" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="yes">
+ <avp name="Feature-List" code="630" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="no">
<type type-name="Unsigned32"/>
</avp>
<!-- GROUPED -->
- <avp name="Supported-Applications" code="631" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="yes">
+ <avp name="Supported-Applications" code="631" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="no">
<grouped>
<gavp name="Auth-Application-Id"/>
<gavp name="Acct-Application-Id"/>
@@ -299,6 +299,12 @@
<gavp name="Secondary-Charging-Collection-Function-Name"/>
</grouped>
</avp>
+ <!-- GROUPED -->
+ <avp name="Associated-Identities" code="632" mandatory="must" vendor-bit="must" vendor-id="TGPP" may-encrypt="no">
+ <grouped>
+ <gavp name="User-Name"/>
+ </grouped>
+ </avp>
<!-- ************************ END IMS Cx Dx AVPS ******************* -->
diff --git a/epan/dissectors/packet-diameter.c b/epan/dissectors/packet-diameter.c
index 9b1d6b9cfc..13f5459a5a 100644
--- a/epan/dissectors/packet-diameter.c
+++ b/epan/dissectors/packet-diameter.c
@@ -55,6 +55,7 @@
#include <epan/prefs.h>
#include <epan/sminmpec.h>
#include <epan/emem.h>
+#include <epan/expert.h>
#include "packet-tcp.h"
#include "packet-sip.h"
@@ -1134,11 +1135,12 @@ diameter_avp_get_type(guint32 avpCode, guint32 vendorId){
/* return an avp name from the code */
static gchar *
-diameter_avp_get_name(guint32 avpCode, guint32 vendorId)
+diameter_avp_get_name(guint32 avpCode, guint32 vendorId, gboolean *AVPFound)
{
gchar *buffer;
avpInfo *probe;
gchar *vendorName=NULL;
+ *AVPFound = TRUE; /* will set to FALSE only if fail to match */
if (vendorId)
vendorName = diameter_vendor_to_str(vendorId, FALSE);
@@ -1167,9 +1169,11 @@ diameter_avp_get_name(guint32 avpCode, guint32 vendorId)
/* If we don't find it, build a name string */
buffer=ep_alloc(64);
- g_snprintf(buffer, 64, "Unknown AVP:0x%08x", avpCode);
+ g_snprintf(buffer, 64, "Unknown AVP:0x%08x (%d)", avpCode, avpCode);
+ *AVPFound = FALSE;
return buffer;
} /* diameter_avp_get_name */
+
static const gchar *
diameter_avp_get_value(guint32 avpCode, guint32 vendorId, guint32 avpValue)
{
@@ -1625,486 +1629,498 @@ safe_dissect_mip(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;
- const gchar *avpTypeString;
- const gchar *avpNameString;
- const gchar *valstr;
- guint32 vendorId=0;
- gchar *vendorName;
- int hdrLength;
- int fixAmt;
- proto_tree *avpi_tree;
- size_t offset = 0;
- tvbuff_t *group_tvb;
- proto_tree *group_tree;
- proto_item *grouptf;
- proto_item *avptf;
- char *buffer;
- int BadPacket = FALSE;
- guint32 avpLength;
- guint8 flags;
- proto_item *tf;
- proto_tree *flags_tree;
-
- gint32 packetLength;
- size_t avpDataLength;
- int avpType;
- gchar *flagstr="<None>";
- const 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) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: AVP Payload too short: %d bytes less than min size (%ld bytes))",
- packetLength, (long)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 = 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) {
- int fslen;
-
-#define FLAG_STR_LEN 64
- flagstr=ep_alloc(FLAG_STR_LEN);
- flagstr[0]=0;
- fslen=0;
- for (i = 0; i < 8; i++) {
- bpos = 1 << i;
- if (flags & bpos) {
- if (flagstr[0]) {
- fslen+=MIN(FLAG_STR_LEN-fslen,
- g_snprintf(flagstr+fslen, FLAG_STR_LEN-fslen, ", "));
- }
- fslen+=MIN(FLAG_STR_LEN-fslen,
- g_snprintf(flagstr+fslen, FLAG_STR_LEN-fslen, "%s", fstr[i]));
- }
- }
- if (flagstr[0] == 0) {
- flagstr="<None>";
- }
- }
-
- /* Dissect our vendor id if it exists and set hdr length */
- if (flags & AVP_FLAGS_V) {
- vendorId = g_ntohl(avph.avp_vendorId);
- /* Vendor id */
- hdrLength = sizeof(e_avphdr);
- } else {
- /* No vendor */
- hdrLength = sizeof(e_avphdr) -
- sizeof(guint32);
- vendorId = 0;
- }
-
- if (vendorId) {
- vendorName=diameter_vendor_to_str(vendorId, TRUE);
- } else {
- vendorName="";
- }
-
- /* Check for bad length */
- if (avpLength < MIN_AVP_SIZE ||
- ((long)avpLength > packetLength)) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: AVP payload size invalid: avp_length: %ld bytes, "
- "min: %ld bytes, packetLen: %d",
- (long)avpLength, (long)MIN_AVP_SIZE,
- packetLength);
- BadPacket = TRUE;
- }
-
- /* Check for bad flags */
- if (flags & AVP_FLAGS_RESERVED) {
- if ( suppress_console_output == FALSE )
- 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) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: Bad AVP: Bad new length (%d bytes) ",
- packetLength);
- BadPacket = TRUE;
- }
-
- /* Make avp Name & type */
- avpTypeString=val_to_str(diameter_avp_get_type(avph.avp_code,vendorId),
- TypeValues,
- "Unknown-Type: 0x%08x");
- avpNameString=diameter_avp_get_name(avph.avp_code, vendorId);
-
- 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_value(avpi_tree, hf_diameter_avp_code,
- tvb, offset, 4, avph.avp_code, "%s (%u)", avpNameString,avph.avp_code);
- offset += 4;
-
- tf = proto_tree_add_uint_format_value(avpi_tree, hf_diameter_avp_flags, tvb,
- offset, 1, 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_value(avpi_tree, hf_diameter_avp_vendor_id,
- tvb, offset, 4, vendorId, "%s", vendorName);
- 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,
- tvb_get_ptr(tvb, offset, tvb_length(tvb) - offset),
- "Bad AVP (Suspect Data Not Dissected)");
+ /* adds the attribute value pairs to the tree */
+ e_avphdr avph;
+ const gchar *avpTypeString;
+ const gchar *avpNameString;
+ const gchar *valstr;
+ guint32 vendorId=0;
+ gchar *vendorName;
+ int hdrLength;
+ int fixAmt;
+ proto_tree *avpi_tree;
+ size_t offset = 0;
+ tvbuff_t *group_tvb;
+ proto_tree *group_tree;
+ proto_item *grouptf;
+ proto_item *avptf;
+ char *buffer;
+ int BadPacket = FALSE;
+ guint32 avpLength;
+ guint8 flags;
+ proto_item *tf;
+ proto_tree *flags_tree;
+
+ gint32 packetLength;
+ size_t avpDataLength;
+ int avpType;
+ gchar *flagstr="<None>";
+ const 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;
- }
-
- avpType=diameter_avp_get_type(avph.avp_code,vendorId);
-
- switch(avpType) {
- case DIAMETER_GROUPED:
- buffer=ep_alloc(256);
- g_snprintf(buffer, 256, "%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:
- {
- 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:
- {
- 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:
- {
- switch(gbl_version) {
- case DIAMETER_V16:
- if (avpDataLength == 4) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
- tvb, offset, avpDataLength, FALSE);
- } else if (avpDataLength == 16) {
- 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,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Address Length (Address in RFC3588 format?)");
- }
- break;
- case DIAMETER_RFC:
- /* Indicate the address family */
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_addrfamily,
- tvb, offset, 2, FALSE);
- if (tvb_get_ntohs(tvb, offset) == 0x0001) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
- tvb, offset+2, avpDataLength-2, FALSE);
- } else if (tvb_get_ntohs(tvb, offset) == 0x0002) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v6addr,
- tvb, offset+2, avpDataLength-2, FALSE);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Can't Parse Address Family %d (Address in draft v16 format?)",
- (int)tvb_get_ntohs(tvb, offset));
- }
- break;
- }
- }
- break;
+ }
- case DIAMETER_INTEGER32:
- 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");
+ /* Spin around until we run out of packet */
+ while (packetLength > 0 )
+ {
+ gboolean AVP_code_found;
+
+ /* Check for short packet */
+ if (packetLength < (long)MIN_AVP_SIZE) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: AVP Payload too short: %d bytes less than min size (%ld bytes))",
+ packetLength, (long)MIN_AVP_SIZE);
+ BadPacket = TRUE;
+ /* Don't even bother trying to parse a short packet. */
+ return;
}
- break;
- case DIAMETER_UNSIGNED32:
- if (avpDataLength == 4) {
- guint32 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);
- } 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_UNSIGNED32ENUM:
- if (avpDataLength == 4) {
- guint32 data;
+ /* Copy our header */
+ tvb_memcpy(tvb, (guint8*) &avph, offset, MIN((long)sizeof(avph),packetLength));
+
+ /* Fix the byte ordering */
+ 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) {
+ int fslen;
- 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);
- } 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");
+#define FLAG_STR_LEN 64
+ flagstr=ep_alloc(FLAG_STR_LEN);
+ flagstr[0]=0;
+ fslen=0;
+ for (i = 0; i < 8; i++) {
+ bpos = 1 << i;
+ if (flags & bpos) {
+ if (flagstr[0]) {
+ fslen+=MIN(FLAG_STR_LEN-fslen,
+ g_snprintf(flagstr+fslen, FLAG_STR_LEN-fslen, ", "));
+ }
+ fslen+=MIN(FLAG_STR_LEN-fslen,
+ g_snprintf(flagstr+fslen, FLAG_STR_LEN-fslen, "%s", fstr[i]));
+ }
+ }
+ if (flagstr[0] == 0) {
+ flagstr="<None>";
+ }
}
- break;
- case DIAMETER_INTEGER64:
- if (avpDataLength == 8) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64,
- tvb, offset, 8, FALSE);
+ /* Dissect our vendor id if it exists and set hdr length */
+ if (flags & AVP_FLAGS_V) {
+ vendorId = g_ntohl(avph.avp_vendorId);
+ /* Vendor id */
+ hdrLength = sizeof(e_avphdr);
} 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");
+ /* No vendor */
+ hdrLength = sizeof(e_avphdr) - sizeof(guint32);
+ vendorId = 0;
}
- break;
- case DIAMETER_UNSIGNED64:
- if (avpDataLength == 8) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64,
- tvb, offset, 8, FALSE);
+ if (vendorId) {
+ vendorName=diameter_vendor_to_str(vendorId, TRUE);
} 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");
+ vendorName="";
}
- break;
- case DIAMETER_TIME:
- if (avpDataLength == 4) {
- nstime_t data;
- struct tm *gmtp;
-
- data.secs = tvb_get_ntohl(tvb, offset);
- /* Present the time as UTC, Time before 00:00:00 UTC, January 1, 1970 can't be presented correctly */
- if ( data.secs >= NTP_TIME_DIFF){
- data.secs -= NTP_TIME_DIFF;
- data.nsecs = 0;
-
- gmtp = gmtime(&data.secs);
- buffer=ep_alloc(64);
- strftime(buffer, 64,
- "%a, %d %b %Y %H:%M:%S UTC", gmtp);
-
- 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! Time before 00:00:00 UTC, January 1, 1970");
- }
- } 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");
+ /* Check for bad length */
+ if (avpLength < MIN_AVP_SIZE ||
+ ((long)avpLength > packetLength))
+ {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: AVP payload size invalid: avp_length: %ld bytes, "
+ "min: %ld bytes, packetLen: %d",
+ (long)avpLength, (long)MIN_AVP_SIZE, packetLength);
+ BadPacket = TRUE;
}
- break;
- case DIAMETER_ENUMERATED:
- if (avpDataLength == 4) {
- guint32 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);
- } 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");
+ /* Check for bad flags */
+ if (flags & AVP_FLAGS_RESERVED) {
+ if ( suppress_console_output == FALSE )
+ 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;
+ */
}
- break;
- case DIAMETER_VENDOR_ID:
- if (avpDataLength == 4) {
- proto_tree_add_item(avpi_tree, hf_diameter_vendor_id, 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 Vendor ID Length");
+ /*
+ * 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) {
+ if ( suppress_console_output == FALSE )
+ g_warning("Diameter: Bad AVP: Bad new length (%d bytes) ",
+ packetLength);
+ BadPacket = TRUE;
}
- break;
-
- case DIAMETER_APPLICATION_ID:
- if (avpDataLength == 4) {
- guint32 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,
- "Application ID: %s %d (0x%08x)",
- valstr, 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 Application ID Length");
- }
- break;
+ /* Make avp Name & type */
+ avpTypeString=val_to_str(diameter_avp_get_type(avph.avp_code,vendorId),
+ TypeValues,
+ "Unknown-Type: 0x%08x");
+ avpNameString=diameter_avp_get_name(avph.avp_code, vendorId, &AVP_code_found);
- case DIAMETER_MIP_REG_REQ:
- safe_dissect_mip(tvb, pinfo, avpi_tree, offset, avpDataLength);
- break;
+ 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);
- case DIAMETER_URI:
- proto_tree_add_item(avpi_tree, hf_diameter_avp_diameter_uri,
- tvb, offset, avpDataLength, FALSE);
- break;
+ if (avpi_tree !=NULL)
+ {
+ /* Command Code */
+ proto_item *ti;
+ ti = proto_tree_add_uint_format_value(avpi_tree, hf_diameter_avp_code,
+ tvb, offset, 4, avph.avp_code, "%s (%u)",
+ avpNameString,avph.avp_code);
+ if (!AVP_code_found)
+ {
+ printf("adding expert info!\n");
+ expert_add_info_format(pinfo, ti,
+ PI_UNDECODED, PI_NOTE,
+ "AVP info not available (code %u)",
+ avph.avp_code);
+ }
+ offset += 4;
- case DIAMETER_SESSION_ID:
- proto_tree_add_item(avpi_tree, hf_diameter_avp_session_id,
- tvb, offset, avpDataLength, FALSE);
- break;
+ tf = proto_tree_add_uint_format_value(avpi_tree, hf_diameter_avp_flags, tvb,
+ offset, 1, 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_value(avpi_tree, hf_diameter_avp_vendor_id,
+ tvb, offset, 4, vendorId, "%s", vendorName);
+ offset += 4;
+ }
- case DIAMETER_PUBLIC_ID:
- {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_public_id,
- tvb, offset, avpDataLength, FALSE);
- /* This is a SIP address, to be able to filter the SIP messages
- * belonging to this Diameter session add this to the SIP filter.
- */
- dfilter_store_sip_from_addr(tvb, avpi_tree, offset, avpDataLength);
- }
- break;
- case DIAMETER_PRIVATE_ID:
- {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_private_id,
- tvb, offset, avpDataLength, FALSE);
- }
+ avpDataLength = avpLength - hdrLength;
- default:
- case DIAMETER_OCTET_STRING:
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Hex Data Highlighted Below");
- break;
+ /*
+ * 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,
+ tvb_get_ptr(tvb, offset, tvb_length(tvb) - offset),
+ "Bad AVP (Suspect Data Not Dissected)");
+ return;
+ }
- } /* switch type */
- } /* avpi_tree != null */
- offset += (avpLength - hdrLength);
- offset += fixAmt; /* fix byte alignment */
- } /* loop */
+ avpType=diameter_avp_get_type(avph.avp_code,vendorId);
+
+ switch(avpType)
+ {
+ case DIAMETER_GROUPED:
+ buffer=ep_alloc(256);
+ g_snprintf(buffer, 256, "%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:
+ {
+ 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:
+ {
+ 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:
+ {
+ switch(gbl_version)
+ {
+ case DIAMETER_V16:
+ if (avpDataLength == 4) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
+ tvb, offset, avpDataLength, FALSE);
+ } else if (avpDataLength == 16) {
+ 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,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Address Length (Address in RFC3588 format?)");
+ }
+ break;
+ case DIAMETER_RFC:
+ /* Indicate the address family */
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_addrfamily,
+ tvb, offset, 2, FALSE);
+ if (tvb_get_ntohs(tvb, offset) == 0x0001) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
+ tvb, offset+2, avpDataLength-2, FALSE);
+ } else if (tvb_get_ntohs(tvb, offset) == 0x0002) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v6addr,
+ tvb, offset+2, avpDataLength-2, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Can't Parse Address Family %d (Address in draft v16 format?)",
+ (int)tvb_get_ntohs(tvb, offset));
+ }
+ break;
+ }
+ }
+ break;
+
+ case DIAMETER_INTEGER32:
+ 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;
+
+ 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);
+ } 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_UNSIGNED32ENUM:
+ if (avpDataLength == 4) {
+ guint32 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);
+ } 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_INTEGER64:
+ 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:
+ 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:
+ if (avpDataLength == 4) {
+ nstime_t data;
+ struct tm *gmtp;
+
+ data.secs = tvb_get_ntohl(tvb, offset);
+ /* Present the time as UTC, Time before 00:00:00 UTC, January 1, 1970 can't be presented correctly */
+ if ( data.secs >= NTP_TIME_DIFF){
+ data.secs -= NTP_TIME_DIFF;
+ data.nsecs = 0;
+
+ gmtp = gmtime(&data.secs);
+ buffer=ep_alloc(64);
+ strftime(buffer, 64, "%a, %d %b %Y %H:%M:%S UTC", gmtp);
+
+ 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! Time before 00:00:00 UTC, January 1, 1970");
+ }
+ } 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;
+
+ 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);
+ } 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) {
+ proto_tree_add_item(avpi_tree, hf_diameter_vendor_id, 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 Vendor ID Length");
+ }
+ break;
+
+ case DIAMETER_APPLICATION_ID:
+ if (avpDataLength == 4) {
+ guint32 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,
+ "Application ID: %s %d (0x%08x)",
+ valstr, 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 Application ID Length");
+ }
+ break;
+
+ case DIAMETER_MIP_REG_REQ:
+ safe_dissect_mip(tvb, pinfo, avpi_tree, offset, avpDataLength);
+ break;
+
+ case DIAMETER_URI:
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_diameter_uri,
+ tvb, offset, avpDataLength, FALSE);
+ break;
+
+ case DIAMETER_SESSION_ID:
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_session_id,
+ tvb, offset, avpDataLength, FALSE);
+ break;
+
+ case DIAMETER_PUBLIC_ID:
+ {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_public_id,
+ tvb, offset, avpDataLength, FALSE);
+ /* This is a SIP address, to be able to filter the SIP messages
+ * belonging to this Diameter session add this to the SIP filter.
+ */
+ dfilter_store_sip_from_addr(tvb, avpi_tree, offset, avpDataLength);
+ }
+ break;
+ case DIAMETER_PRIVATE_ID:
+ {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_private_id,
+ tvb, offset, avpDataLength, FALSE);
+ }
+
+ default:
+ case DIAMETER_OCTET_STRING:
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Hex Data Highlighted Below");
+ break;
+ } /* switch type */
+ } /* avpi_tree != null */
+ offset += (avpLength - hdrLength);
+ offset += fixAmt; /* fix byte alignment */
+ } /* loop */
} /* dissect_avps */