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