diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-07-30 20:08:44 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-07-30 20:08:44 +0000 |
commit | 76a85d57644c9a25e4b7ee0ee9504914183ffe60 (patch) | |
tree | 5ebf64f196279f6d53d8ce52c8e7408bcb9bc42b /packet-diameter.c | |
parent | 2997acf2ccc4064ac152980eaf73bdceb5da11f6 (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.c | 1302 |
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",<); + 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; |