2000-07-30 07:16:11 +00:00
|
|
|
/* packet-diameter.c
|
|
|
|
* Routines for DIAMETER packet disassembly
|
|
|
|
*
|
2001-08-04 19:50:33 +00:00
|
|
|
* $Id: packet-diameter.c,v 1.26 2001/08/04 19:50:33 guy Exp $
|
2000-07-30 07:16:11 +00:00
|
|
|
*
|
2001-02-19 23:14:02 +00:00
|
|
|
* Copyright (c) 2001 by David Frascone <dave@frascone.com>
|
2000-07-30 07:16:11 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
2001-05-27 21:38:46 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
2000-07-30 07:16:11 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
|
|
# include <sys/types.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_NETINET_IN_H
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2000-11-17 21:00:40 +00:00
|
|
|
#include <string.h>
|
2000-07-30 07:16:11 +00:00
|
|
|
#include <ctype.h>
|
2000-07-31 04:09:54 +00:00
|
|
|
#include <time.h>
|
2000-07-30 07:16:11 +00:00
|
|
|
#include <glib.h>
|
|
|
|
#include "packet.h"
|
|
|
|
#include "resolv.h"
|
|
|
|
#include "prefs.h"
|
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
/* This must be defined before we include packet-diameter-defs.h s*/
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
/* Valid data types */
|
2000-07-30 07:16:11 +00:00
|
|
|
typedef enum {
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
2000-07-30 07:16:11 +00:00
|
|
|
|
|
|
|
#include "packet-diameter-defs.h"
|
|
|
|
|
|
|
|
#define NTP_TIME_DIFF (2208988800UL)
|
|
|
|
|
2000-10-21 03:24:37 +00:00
|
|
|
#define TCP_PORT_DIAMETER 1812
|
|
|
|
#define SCTP_PORT_DIAMETER 1812
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
static const true_false_string flags_set_truth = {
|
|
|
|
"Set",
|
|
|
|
"Not set"
|
|
|
|
};
|
|
|
|
|
|
|
|
static const true_false_string reserved_set = {
|
|
|
|
"*** Error! Reserved Bit is Set",
|
|
|
|
"Ok"
|
|
|
|
};
|
2000-07-30 07:16:11 +00:00
|
|
|
static int proto_diameter = -1;
|
|
|
|
static int hf_diameter_length = -1;
|
|
|
|
static int hf_diameter_code = -1;
|
2001-04-10 21:49:23 +00:00
|
|
|
static int hf_diameter_hopbyhopid =-1;
|
|
|
|
static int hf_diameter_endtoendid =-1;
|
2001-02-19 23:14:02 +00:00
|
|
|
static int hf_diameter_reserved = -1;
|
|
|
|
static int hf_diameter_version = -1;
|
|
|
|
static int hf_diameter_vendor_id = -1;
|
2001-07-30 20:08:44 +00:00
|
|
|
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;
|
2001-02-19 23:14:02 +00:00
|
|
|
|
|
|
|
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;
|
2001-07-30 20:08:44 +00:00
|
|
|
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;
|
2001-02-19 23:14:02 +00:00
|
|
|
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;
|
|
|
|
static int hf_diameter_avp_data_v6addr = -1;
|
|
|
|
static int hf_diameter_avp_data_time = -1;
|
2000-07-30 07:16:11 +00:00
|
|
|
|
|
|
|
static gint ett_diameter = -1;
|
2001-07-30 20:08:44 +00:00
|
|
|
static gint ett_diameter_flags = -1;
|
2000-07-30 07:16:11 +00:00
|
|
|
static gint ett_diameter_avp = -1;
|
2001-07-30 20:08:44 +00:00
|
|
|
static gint ett_diameter_avp_flags = -1;
|
2000-07-30 07:16:11 +00:00
|
|
|
static gint ett_diameter_avpinfo = -1;
|
|
|
|
|
|
|
|
static char gbl_diameterString[200];
|
|
|
|
static int gbl_diameterTcpPort=TCP_PORT_DIAMETER;
|
|
|
|
static int gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
|
|
|
|
|
|
|
|
typedef struct _e_diameterhdr {
|
2001-07-30 20:08:44 +00:00
|
|
|
guint32 versionLength;
|
|
|
|
guint32 flagsCmdCode;
|
|
|
|
guint32 vendorId;
|
|
|
|
guint32 hopByHopId;
|
|
|
|
guint32 endToEndId;
|
2000-07-30 07:16:11 +00:00
|
|
|
} e_diameterhdr;
|
|
|
|
|
|
|
|
typedef struct _e_avphdr {
|
2001-07-30 20:08:44 +00:00
|
|
|
guint32 avp_code;
|
|
|
|
guint32 avp_flagsLength;
|
|
|
|
guint32 avp_vendorId; /* optional */
|
2000-07-30 07:16:11 +00:00
|
|
|
} e_avphdr;
|
|
|
|
|
|
|
|
#define AUTHENTICATOR_LENGTH 12
|
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
/* Diameter Header Flags */
|
2001-07-30 20:08:44 +00:00
|
|
|
/* RPrrrrrrCCCCCCCCCCCCCCCCCCCCCCCC */
|
|
|
|
#define DIAM_FLAGS_R 0x80
|
|
|
|
#define DIAM_FLAGS_P 0x40
|
2001-02-19 23:14:02 +00:00
|
|
|
#define DIAM_FLAGS_E 0x20
|
2001-07-30 20:08:44 +00:00
|
|
|
#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)
|
2001-02-19 23:14:02 +00:00
|
|
|
|
|
|
|
/* Diameter AVP Flags */
|
2001-07-30 20:08:44 +00:00
|
|
|
#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 */
|
2001-02-19 23:14:02 +00:00
|
|
|
|
|
|
|
#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);
|
2001-07-30 20:08:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
|
|
|
|
/* Code to actually dissect the packets */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Main dissector
|
|
|
|
*/
|
|
|
|
static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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);
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* Copy our header */
|
|
|
|
tvb_memcpy(tvb, (guint8*) &dh, offset, sizeof(dh));
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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");
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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]);
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
if (strlen(flagstr) == 0) {
|
|
|
|
strcpy(flagstr,"<None>");
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* Start looking at the AVPS */
|
|
|
|
/* Make the next tvbuff */
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* Update the lengths */
|
|
|
|
avplength= pktLength - sizeof(e_diameterhdr);
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
avp_tvb = tvb_new_subset(tvb, offset, -1, avplength);
|
|
|
|
avptf = proto_tree_add_text(diameter_tree,
|
|
|
|
tvb, offset, tvb_length(tvb),
|
|
|
|
"Attribute Value Pairs");
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
avp_tree = proto_item_add_subtree(avptf,
|
|
|
|
ett_diameter_avp);
|
|
|
|
if (avp_tree != NULL) {
|
|
|
|
dissect_avps( avp_tvb, pinfo, avp_tree);
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
} /* dissect_diameter */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This function will dissect the AVPs in a diameter packet. It handles
|
|
|
|
* all normal types, and even recursively calls itself for grouped AVPs
|
|
|
|
*/
|
|
|
|
static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
|
|
|
|
{
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* Spin around until we run out of packet */
|
|
|
|
while (packetLength > 0 ) {
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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]);
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
}
|
|
|
|
if (strlen(flagstr) == 0) {
|
|
|
|
strcpy(flagstr,"<None>");
|
|
|
|
}
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
if (vendorId) {
|
|
|
|
strcpy(vendorString,
|
|
|
|
val_to_str(vendorId, diameter_vendor_specific_vendors, "Unknown Vendor: %08x"));
|
|
|
|
} else {
|
|
|
|
vendorString[0]='\0';
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/*
|
|
|
|
* 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) ",
|
2001-04-10 21:49:23 +00:00
|
|
|
packetLength);
|
2001-07-30 20:08:44 +00:00
|
|
|
BadPacket = TRUE;
|
|
|
|
}
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
/* 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;
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
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;
|
|
|
|
}
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
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);
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
group_tree = proto_item_add_subtree(grouptf,
|
|
|
|
ett_diameter_avp);
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
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);
|
|
|
|
}
|
2000-07-30 07:16:11 +00:00
|
|
|
break;
|
2001-07-30 20:08:44 +00:00
|
|
|
|
|
|
|
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);
|
2000-07-30 07:16:11 +00:00
|
|
|
break;
|
2001-07-30 20:08:44 +00:00
|
|
|
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);
|
2000-07-30 07:16:11 +00:00
|
|
|
break;
|
2001-07-30 20:08:44 +00:00
|
|
|
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");
|
|
|
|
}
|
2000-07-30 07:16:11 +00:00
|
|
|
break;
|
2001-02-16 21:41:00 +00:00
|
|
|
|
2001-07-30 20:08:44 +00:00
|
|
|
case DIAMETER_INTEGER32:
|
2000-07-30 07:16:11 +00:00
|
|
|
{
|
2001-07-30 20:08:44 +00:00
|
|
|
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:
|
2001-02-19 23:14:02 +00:00
|
|
|
{
|
2001-07-30 20:08:44 +00:00
|
|
|
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 );
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DIAMETER_INTEGER64:
|
2001-02-19 23:14:02 +00:00
|
|
|
{
|
2001-07-30 20:08:44 +00:00
|
|
|
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,
|
2001-08-04 19:50:33 +00:00
|
|
|
"Value: 0x%016llx (%lld)", data, data );
|
2001-02-19 23:14:02 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
break;
|
|
|
|
case DIAMETER_UNSIGNED64:
|
2000-07-30 07:16:11 +00:00
|
|
|
{
|
2001-07-30 20:08:44 +00:00
|
|
|
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 );
|
2000-07-30 07:16:11 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
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);
|
2000-07-30 07:16:11 +00:00
|
|
|
}
|
2001-07-30 20:08:44 +00:00
|
|
|
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 */
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-02-23 19:26:26 +00:00
|
|
|
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
void
|
|
|
|
proto_reg_handoff_diameter(void)
|
|
|
|
{
|
|
|
|
static int Initialized=FALSE;
|
|
|
|
static int TcpPort=0;
|
|
|
|
static int SctpPort=0;
|
2001-02-23 19:26:26 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
if (Initialized) {
|
|
|
|
dissector_delete("tcp.port", TcpPort, dissect_diameter);
|
2001-02-23 19:26:26 +00:00
|
|
|
dissector_delete("sctp.port", SctpPort, dissect_diameter);
|
2001-02-19 23:14:02 +00:00
|
|
|
} else {
|
|
|
|
Initialized=TRUE;
|
2000-07-30 07:16:11 +00:00
|
|
|
}
|
2001-02-16 21:41:00 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
/* set port for future deletes */
|
|
|
|
TcpPort=gbl_diameterTcpPort;
|
|
|
|
SctpPort=gbl_diameterSctpPort;
|
2001-02-16 21:41:00 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
strcpy(gbl_diameterString, "Diameter Protocol");
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
/* g_warning ("Diameter: Adding tcp dissector to port %d",
|
|
|
|
gbl_diameterTcpPort); */
|
|
|
|
dissector_add("tcp.port", gbl_diameterTcpPort, dissect_diameter,
|
|
|
|
proto_diameter);
|
2001-02-23 19:26:26 +00:00
|
|
|
dissector_add("sctp.port", gbl_diameterSctpPort,
|
2001-02-19 23:14:02 +00:00
|
|
|
dissect_diameter, proto_diameter);
|
2000-07-30 07:16:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* registration with the filtering engine */
|
|
|
|
void
|
|
|
|
proto_register_diameter(void)
|
|
|
|
{
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2000-07-30 07:16:11 +00:00
|
|
|
static hf_register_info hf[] = {
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_version,
|
2001-07-30 20:08:44 +00:00
|
|
|
{ "Version", "diameter.version", FT_UINT8, BASE_HEX, NULL, 0x00,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2000-07-30 07:16:11 +00:00
|
|
|
{ &hf_diameter_length,
|
2001-07-30 20:08:44 +00:00
|
|
|
{ "Length","diameter.length", FT_UINT24, BASE_DEC, NULL, 0x0,
|
|
|
|
"", HFILL }},
|
|
|
|
|
|
|
|
{ &hf_diameter_flags,
|
|
|
|
{ "Flags", "diameter.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"", HFILL }},
|
2001-07-30 20:08:44 +00:00
|
|
|
{ &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 }},
|
2001-04-10 21:49:23 +00:00
|
|
|
{ &hf_diameter_hopbyhopid,
|
|
|
|
{ "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
|
2001-06-18 02:18:27 +00:00
|
|
|
BASE_HEX, NULL, 0x0, "", HFILL }},
|
2001-04-10 21:49:23 +00:00
|
|
|
{ &hf_diameter_endtoendid,
|
|
|
|
{ "End-to-End Identifier", "diameter.endtoendid", FT_UINT32,
|
2001-06-18 02:18:27 +00:00
|
|
|
BASE_HEX, NULL, 0x0, "", HFILL }},
|
2000-07-30 07:16:11 +00:00
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_code,
|
|
|
|
{ "AVP Code","diameter.avp.code", FT_UINT32, BASE_DEC,
|
2001-07-30 20:08:44 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_length,
|
2001-07-30 20:08:44 +00:00
|
|
|
{ "AVP Length","diameter.avp.length", FT_UINT24, BASE_DEC,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-07-30 20:08:44 +00:00
|
|
|
|
|
|
|
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_flags,
|
|
|
|
{ "AVP Flags","diameter.avp.flags", FT_UINT8, BASE_HEX,
|
2001-07-30 20:08:44 +00:00
|
|
|
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 }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_vendor_id,
|
|
|
|
{ "AVP Vendor Id","diameter.avp.vendorId", FT_UINT32, BASE_DEC,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-07-30 20:08:44 +00:00
|
|
|
{ &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 }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_data_uint32,
|
|
|
|
{ "AVP Data","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_data_int32,
|
|
|
|
{ "AVP Data","diameter.avp.data.int32", FT_INT32, BASE_DEC,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_data_bytes,
|
|
|
|
{ "AVP Data","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
|
|
|
|
{ &hf_diameter_avp_data_string,
|
|
|
|
{ "AVP Data","diameter.avp.data.string", FT_STRING, BASE_NONE,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_data_v4addr,
|
|
|
|
{ "AVP Data","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_data_v6addr,
|
|
|
|
{ "AVP Data","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
{ &hf_diameter_avp_data_time,
|
|
|
|
{ "AVP Data","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
|
2001-06-18 02:18:27 +00:00
|
|
|
NULL, 0x0, "", HFILL }},
|
2001-02-19 23:14:02 +00:00
|
|
|
|
2000-07-30 07:16:11 +00:00
|
|
|
};
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_diameter,
|
2001-07-30 20:08:44 +00:00
|
|
|
&ett_diameter_flags,
|
2000-07-30 07:16:11 +00:00
|
|
|
&ett_diameter_avp,
|
2001-07-30 20:08:44 +00:00
|
|
|
&ett_diameter_avp_flags,
|
2000-07-30 07:16:11 +00:00
|
|
|
&ett_diameter_avpinfo
|
|
|
|
};
|
|
|
|
module_t *diameter_module;
|
2001-01-03 06:56:03 +00:00
|
|
|
|
|
|
|
proto_diameter = proto_register_protocol (gbl_diameterString,
|
|
|
|
"DIAMETER", "diameter");
|
|
|
|
proto_register_field_array(proto_diameter, hf, array_length(hf));
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
|
|
|
|
2000-07-30 07:16:11 +00:00
|
|
|
/* Register a configuration option for port */
|
2001-01-03 07:53:48 +00:00
|
|
|
diameter_module = prefs_register_protocol(proto_diameter,
|
2000-07-30 07:16:11 +00:00
|
|
|
proto_reg_handoff_diameter);
|
|
|
|
prefs_register_uint_preference(diameter_module, "tcp.port",
|
2000-08-03 09:30:32 +00:00
|
|
|
"DIAMETER TCP Port",
|
2000-07-30 07:16:11 +00:00
|
|
|
"Set the TCP port for DIAMETER messages",
|
|
|
|
10,
|
|
|
|
&gbl_diameterTcpPort);
|
|
|
|
prefs_register_uint_preference(diameter_module, "sctp.port",
|
|
|
|
"DIAMETER SCTP Port",
|
|
|
|
"Set the SCTP port for DIAMETER messages",
|
|
|
|
10,
|
|
|
|
&gbl_diameterSctpPort);
|
|
|
|
}
|