/* packet-diameter.c
* Routines for Diameter packet disassembly
*
- * $Id: packet-diameter.c,v 1.30 2001/11/03 04:09:46 guy Exp $
+ * $Id: packet-diameter.c,v 1.62 2004/03/05 22:25:23 obiot Exp $
*
* Copyright (c) 2001 by David Frascone <dave@frascone.com>
*
#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>
#include <string.h>
+#include <errno.h>
#include <ctype.h>
#include <time.h>
#include <glib.h>
-#include <filesystem.h>
+#include <epan/filesystem.h>
#include "xmlstub.h"
-#include "packet.h"
-#include "resolv.h"
+#include <epan/packet.h>
+#include <epan/resolv.h>
+#include "report_err.h"
#include "prefs.h"
+#include "packet-tcp.h"
+
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
/* This must be defined before we include packet-diameter-defs.h */
DIAMETER_MIP_REG_REQ, /* OctetString */
DIAMETER_VENDOR_ID, /* Integer32 */
DIAMETER_APPLICATION_ID
-
+
} diameterDataType;
typedef struct command_code {
guint32 code;
gchar *name;
- gchar *vendorString;
+ gchar *vendorName;
struct command_code *next;
} CommandCode;
#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 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_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 gint ett_diameter_avp_flags = -1;
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;
-#define DIAMETER_DIR "diameter"
-#define DICT_FN "dictionary.xml"
-static gchar *gbl_diameterDictionary = NULL;
+static guint gbl_diameterTcpPort=TCP_PORT_DIAMETER;
+static guint gbl_diameterSctpPort=SCTP_PORT_DIAMETER;
+
+/* desegmentation of Diameter over TCP */
+static gboolean gbl_diameter_desegment = TRUE;
+
+/* Allow zero as a valid application ID */
+static gboolean allow_zero_as_app_id = FALSE;
+
+#define DICT_FN "diameter/dictionary.xml"
+static gchar *gbl_diameterDictionary;
typedef struct _e_diameterhdr {
guint32 versionLength;
int res, size = 1024;
char chars[1024];
xmlParserCtxtPtr ctxt;
-
+
/* I wonder what kind of a performance hit this is? */
*XmlStub.xmlDoValidityCheckingDefaultValue = checkValid;
-
+
f = fopen(filename, "r");
if (f == NULL) {
- g_warning("Diameter: Unable to open %s", filename);
+ report_open_failure(filename, errno, FALSE);
return NULL;
}
valid=ctxt->valid;
XmlStub.xmlFreeParserCtxt(ctxt);
}
- fclose(f);
+ fclose(f);
/* Check valid */
if (!valid) {
/* Parse our values array, if we have one */
if (values) {
for (i=0; values[i].strptr != NULL; i++) {
- char *valueName=NULL, *valueCode=NULL;
ValueName *ve = NULL;
-
+
ve = g_malloc(sizeof(ValueName));
ve->name = strdup(values[i].strptr);
ve->value = values[i].value;
avpListHead = entry;
return (0);
-
+
} /* addStaticAVP */
/*
* add them too.
*/
static int
-xmlParseAVP(xmlDocPtr doc, xmlNodePtr cur)
+xmlParseAVP(xmlNodePtr cur)
{
char *name=NULL, *description=NULL, *code=NULL, *mayEncrypt=NULL,
*mandatory=NULL, *protected=NULL, *vendorBit=NULL, *vendorName = NULL,
cur = cur->xmlChildrenNode;
while (cur != NULL ) {
- if (!strcasecmp((char *)cur->name, "type")) {
+ if (strcasecmp(cur->name, "type") == 0) {
type = XmlStub.xmlGetProp(cur, "type-name");
- }
- if (!strcasecmp((char *)cur->name, "enum")) {
+ } else if (strcasecmp(cur->name, "enum") == 0) {
char *valueName=NULL, *valueCode=NULL;
ValueName *ve = NULL;
valueName = XmlStub.xmlGetProp(cur, "name");
valueCode = XmlStub.xmlGetProp(cur, "code");
-
+
if (!valueName || !valueCode) {
g_warning( "Error, bad value on avp %s", name);
return (-1);
}
-
+
ve = g_malloc(sizeof(ValueName));
ve->name = strdup(valueName);
ve->value = atol(valueCode);
ve->next = vEntry;
vEntry = ve;
- }
- if (!strcasecmp((char *)cur->name, "grouped")) {
+ } else if (strcasecmp(cur->name, "grouped") == 0) {
/* WORK Recurse here for grouped AVPs */
type = "grouped";
}
}
/* WORK - Handle flags -- for validation later */
-
+
/* And, create the entry */
entry = (avpInfo *)g_malloc(sizeof(avpInfo));
entry->name = g_strdup(name);
entry->code = atol(code);
- if (vendorName)
+ if (vendorName)
entry->vendorName = g_strdup(vendorName);
else
entry->vendorName = NULL;
entry->name = g_strdup(name);
entry->code = code;
if (vendorId)
- entry->vendorString = g_strdup(vendorId);
+ entry->vendorName = g_strdup(vendorId);
else
- entry->vendorString = NULL;
+ entry->vendorName = "None";
/* Add the entry to the list */
entry->next = commandListHead;
* list of commands.
*/
static int
-xmlParseCommand(xmlDocPtr doc, xmlNodePtr cur)
+xmlParseCommand(xmlNodePtr cur)
{
- guint32 vendorId = 0;
char *name, *code, *vendorIdString;
/*
{
ApplicationId *entry;
- if (!name || (id <= 0)) {
- g_warning( "Diameter Error: Inavlid application (name=%p, id=%d)",
+ if (!name || (id < 0) || (id == 0 && !allow_zero_as_app_id)) {
+ g_warning( "Diameter Error: Invalid application (name=%p, id=%d)",
name, id);
return (-1);
} /* Sanity Checks */
g_warning( "Unable to allocate memory");
return (-1);
}
-
+
entry->name = g_strdup(name);
entry->id = id;
-
+
/* Add it to the list */
entry->next = ApplicationIdHead;
ApplicationIdHead = entry;
* This routine will pars in a XML vendor entry.
*/
static int
-xmlParseVendor(xmlDocPtr doc, xmlNodePtr cur)
+xmlParseVendor(xmlNodePtr cur)
{
char *name=NULL, *code=NULL, *id=NULL;
* This routine will either parse in the base protocol, or an application.
*/
static int
-xmlDictionaryParseSegment(xmlDocPtr doc, xmlNodePtr cur, int base)
+xmlDictionaryParseSegment(xmlNodePtr cur, int base)
{
if (!base) {
char *name;
char *id;
-
+
/* Add our application */
id = XmlStub.xmlGetProp(cur, "id");
name = XmlStub.xmlGetProp(cur, "name");
-
+
if (!name || !id) {
/* ERROR!!! */
g_warning("Diameter: Invalid application!: name=\"%s\", id=\"%s\"",
name?name:"NULL", id?id:"NULL");
return -1;
}
-
+
/* Add the application */
if (dictionaryAddApplication(name, atol(id)) != 0) {
/* ERROR! */
}
}
-
+
/*
* Get segment values
*/
cur = cur->xmlChildrenNode;
while (cur != NULL) {
- if (!strcasecmp((char *)cur->name, "avp")) {
+ if (strcasecmp(cur->name, "avp") == 0) {
/* we have an avp!!! */
- xmlParseAVP(doc, cur);
- } else if (!strcasecmp((char *)cur->name, "vendor")) {
+ xmlParseAVP(cur);
+ } else if (strcasecmp(cur->name, "vendor") == 0) {
/* we have a vendor */
- xmlParseVendor(doc, cur);
+ xmlParseVendor(cur);
/* For now, ignore typedefn and text */
- } else if (!strcasecmp((char *)cur->name, "command")) {
+ } else if (strcasecmp(cur->name, "command") == 0) {
/* Found a command */
- xmlParseCommand(doc,cur);
- } else if (!strcasecmp((char *)cur->name, "text")) {
- } else if (!strcasecmp((char *)cur->name, "comment")) {
- } else if (!strcasecmp((char *)cur->name, "typedefn")) {
+ xmlParseCommand(cur);
+ } else if (strcasecmp(cur->name, "text") == 0) {
+ } else if (strcasecmp(cur->name, "comment") == 0) {
+ } else if (strcasecmp(cur->name, "typedefn") == 0) {
/* WORK -- parse in valid types . . . */
} else {
/* IF we got here, we're an error */
} /* xmlDictionaryParseSegment */
/*
- * The main xml parse routine. This will walk through an XML
+ * The main xml parse routine. This will walk through an XML
* dictionary that has been parsed by libxml.
*/
static int
-xmlDictionaryParse(xmlDocPtr doc, xmlNodePtr cur)
+xmlDictionaryParse(xmlNodePtr cur)
{
- /* We should expect a base protocol, followed by multiple applicaitons */
+ /* We should expect a base protocol, followed by multiple applications */
while (cur != NULL) {
- if (!strcasecmp((char *)cur->name, "base")) {
+ if (strcasecmp(cur->name, "base") == 0) {
/* Base protocol. Descend and parse */
- xmlDictionaryParseSegment(doc, cur, 1);
- } else if (!strcasecmp((char *)cur->name, "application")) {
+ xmlDictionaryParseSegment(cur, 1);
+ } else if (strcasecmp(cur->name, "application") == 0) {
/* Application. Descend and parse */
- xmlDictionaryParseSegment(doc, cur, 0);
- } else if (!strcasecmp((char *)cur->name, "text")) {
+ xmlDictionaryParseSegment(cur, 0);
+ } else if (strcasecmp(cur->name, "text") == 0) {
+ /* Ignore text */
+ } else if (strcasecmp(cur->name, "comment") == 0) {
/* Ignore text */
} else {
g_warning( "Diameter: XML Expecting a base or an application (got \"%s\")",
* This routine will call libxml to parse in the dictionary.
*/
static int
-loadXMLDictionary()
+loadXMLDictionary(void)
{
xmlDocPtr doc;
xmlNodePtr cur;
gbl_diameterDictionary);
return -1;
}
-
+
/*
* Check the document is of the right kind
*/
XmlStub.xmlFreeDoc(doc);
return -1;
}
-
+
/*
* Ok, the dictionary has been parsed by libxml, and is valid.
* All we have to do now is read in our information.
*/
- if (xmlDictionaryParse(doc, cur->xmlChildrenNode) != 0) {
+ if (xmlDictionaryParse(cur->xmlChildrenNode) != 0) {
/* Error has already been printed */
return -1;
}
* with the old static data from packet-diameter-defs.h
*/
static void
-initializeDictionaryDefaults()
+initializeDictionaryDefaults(void)
{
int i;
} /* initializeDictionaryDefaults */
-/*
- * This routine will attempt to load the XML dictionary, and on
+/*
+ * This routine will attempt to load the XML dictionary, and on
* failure, will call initializeDictionaryDefaults to load in
* our static dictionary.
*/
static void
-initializeDictionary()
+initializeDictionary(void)
{
/*
- * Using ugly ordering here. If loadLibXML succeeds, then
+ * Using ugly ordering here. If loadLibXML succeeds, then
* loadXMLDictionary will be called. This is one of the few times when
* I think this is prettier than the nested if alternative.
*/
* These routines manipulate the diameter structures.
*/
-/* return command string, based on the code */
+/* return vendor string, based on the id */
static gchar *
-diameter_command_to_str(guint32 commandCode)
-{
- CommandCode *probe;
+diameter_vendor_to_str(guint32 vendorId, gboolean longName) {
+ VendorId *probe;
static gchar buffer[64];
- for (probe=commandListHead; probe; probe=probe->next) {
- if (commandCode == probe->code) {
- return probe->name;
+ for (probe=vendorListHead; probe; probe=probe->next) {
+ if (vendorId == probe->id) {
+ if (longName)
+ return probe->longName;
+ else
+ return probe->name;
}
}
snprintf(buffer, sizeof(buffer),
- "Cmd-0x%08x", commandCode);
+ "Vendor 0x%08x", vendorId);
return buffer;
-}/*diameter_command_to_str */
-/* return vendor string, based on the id */
+} /*diameter_vendor_to_str */
+
+/* return command string, based on the code */
static gchar *
-diameter_vendor_to_str(guint32 vendorId) {
- VendorId *probe;
+diameter_command_to_str(guint32 commandCode, guint32 vendorId)
+{
+ CommandCode *probe;
static gchar buffer[64];
+ gchar *vendorName=NULL;
- for (probe=vendorListHead; probe; probe=probe->next) {
- if (vendorId == probe->id) {
- return probe->longName;
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
+
+ for (probe=commandListHead; probe; probe=probe->next) {
+ if (commandCode == probe->code) {
+ if (vendorId) {
+/* g_warning("Command: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (!strcmp(vendorName, probe->vendorName))
+ /* We found it */
+ return probe->name;
+ } else {
+ /* With no vendor id, the Command's entry should be "None" */
+ if (!strcmp(probe->vendorName, "None")) {
+ /* We found it */
+ return probe->name;
+ }
+ }
}
}
+ g_warning("Diameter: Unable to find name for command code 0x%08x, Vendor \"%u\"!",
+ commandCode, vendorId);
snprintf(buffer, sizeof(buffer),
- "Vendor 0x%08x", vendorId);
+ "Cmd-0x%08x", commandCode);
return buffer;
-} /*diameter_vendor_to_str */
+}/*diameter_command_to_str */
+
/* return application string, based on the id */
static gchar *
diameter_app_to_str(guint32 vendorId) {
} /*diameter_app_to_str */
/* return an avp type, based on the code */
-diameterDataType
-diameter_avp_get_type(guint32 avpCode){
+static diameterDataType
+diameter_avp_get_type(guint32 avpCode, guint32 vendorId){
avpInfo *probe;
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
for (probe=avpListHead; probe; probe=probe->next) {
if (avpCode == probe->code) {
- /* We found it! */
- return probe->type;
+
+ if (vendorId) {
+/* g_warning("AvpType: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (probe->vendorName && (!strcmp(vendorName, probe->vendorName)))
+ /* We found it! */
+ return probe->type;
+ } else {
+ /* No Vendor ID -- vendorName should be null */
+ if (!probe->vendorName)
+ /* We found it! */
+ return probe->type;
+ }
}
}
-
+
/* If we don't find it, assume it's data */
- g_warning("Diameter: Unable to find type for avpCode %d!", avpCode);
+ g_warning("Diameter: Unable to find type for avpCode %u, Vendor %u!", avpCode,
+ vendorId);
return DIAMETER_OCTET_STRING;
} /* diameter_avp_get_type */
/* return an avp name from the code */
static gchar *
-diameter_avp_get_name(guint32 avpCode)
+diameter_avp_get_name(guint32 avpCode, guint32 vendorId)
{
static gchar buffer[64];
avpInfo *probe;
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
for (probe=avpListHead; probe; probe=probe->next) {
if (avpCode == probe->code) {
- /* We found it! */
- return probe->name;
+ if (vendorId) {
+/* g_warning("AvpName: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (probe->vendorName && (!strcmp(vendorName, probe->vendorName)))
+ /* We found it! */
+ return probe->name;
+ } else {
+ /* No Vendor ID -- vendorName should be null */
+ if (!probe->vendorName)
+ /* We found it! */
+ return probe->name;
+ }
}
}
+
+ g_warning("Diameter: Unable to find name for AVP 0x%08x, Vendor %u!",
+ avpCode, vendorId);
+
/* 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)
+diameter_avp_get_value(guint32 avpCode, guint32 vendorId, guint32 avpValue)
{
static gchar buffer[64];
avpInfo *probe;
+ gchar *vendorName=NULL;
+
+ if (vendorId)
+ vendorName = diameter_vendor_to_str(vendorId, FALSE);
for (probe=avpListHead; probe; probe=probe->next) {
if (avpCode == probe->code) {
- ValueName *vprobe;
- for(vprobe=probe->values; vprobe; vprobe=vprobe->next) {
- if (avpValue == vprobe->value) {
- return vprobe->name;
+ if (vendorId) {
+/* g_warning("AvpValue: Comparing \"%s\" to \"%s\"", */
+/* vendorName?vendorName:"(null)", */
+/* probe->vendorName?probe->vendorName:"(null)"); */
+ /* Now check the vendor name */
+ if (probe->vendorName && (!strcmp(vendorName, probe->vendorName))) {
+ ValueName *vprobe;
+ for(vprobe=probe->values; vprobe; vprobe=vprobe->next) {
+ if (avpValue == vprobe->value) {
+ return vprobe->name;
+ }
+ }
+ sprintf(buffer, "Unknown Value: 0x%08x", avpValue);
+ return buffer;
+ }
+ } else {
+ if (!probe->vendorName) {
+ ValueName *vprobe;
+ for(vprobe=probe->values; vprobe; vprobe=vprobe->next) {
+ if (avpValue == vprobe->value) {
+ return vprobe->name;
+ }
+ }
+ sprintf(buffer, "Unknown Value: 0x%08x", avpValue);
+ return buffer;
}
}
- sprintf(buffer, "Unknown Value: 0x%08x", avpValue);
- return buffer;
}
}
/* If we don't find the avp, build a value string */
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 */
+static gboolean
+check_diameter(tvbuff_t *tvb)
+{
+ if (!tvb_bytes_exist(tvb, 0, 1))
+ return FALSE; /* not enough bytes to check the version */
+ if (tvb_get_guint8(tvb, 0) != 1)
+ return FALSE; /* not version 1 */
+
+ /* XXX - fetch length and make sure it's at least MIN_DIAMETER_SIZE?
+ Fetch flags and check that none of the DIAM_FLAGS_RESERVED bits
+ are set? */
+ return TRUE;
+}
+
/*
* Main dissector
*/
-static void dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static void
+dissect_diameter_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
tvbuff_t *avp_tvb;
proto_tree *diameter_tree;
e_diameterhdr dh;
- size_t offset=0;
+ int offset=0;
size_t avplength;
proto_tree *avp_tree;
proto_item *avptf;
guint8 version, flags;
gchar flagstr[64] = "<None>";
gchar *fstr[] = {"RSVD7", "RSVD6", "RSVD5", "RSVD4", "RSVD3", "Error", "Proxyable", "Request" };
- gchar commandString[64], vendorString[64];
+ gchar commandString[64], vendorName[64];
gint i;
guint bpos;
static int initialized=FALSE;
initializeDictionary();
initialized=TRUE;
}
-
+
/* 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);
-
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Diameter");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, 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);
+ dh.versionLength = g_ntohl(dh.versionLength);
+ dh.flagsCmdCode = g_ntohl(dh.flagsCmdCode);
+ dh.vendorId = g_ntohl(dh.vendorId);
+ dh.hopByHopId = g_ntohl(dh.hopByHopId);
+ dh.endToEndId = g_ntohl(dh.endToEndId);
if (dh.vendorId) {
- strcpy(vendorString,
- diameter_vendor_to_str(dh.vendorId));
+ strcpy(vendorName,
+ diameter_vendor_to_str(dh.vendorId, TRUE));
} else {
- strcpy(vendorString, "None");
+ strcpy(vendorName, "None");
}
commandCode = DIAM_GET_COMMAND(dh);
/* Set up our flags */
- if (check_col(pinfo->fd, COL_INFO) || tree) {
+ if (check_col(pinfo->cinfo, COL_INFO) || tree) {
flagstr[0]=0;
for (i = 0; i < 8; i++) {
bpos = 1 << i;
strcpy(flagstr,"<None>");
}
}
-
+
/* Set up our commandString */
- strcpy(commandString, diameter_command_to_str(commandCode));
- if (flags & DIAM_FLAGS_R)
+ strcpy(commandString, diameter_command_to_str(commandCode, dh.vendorId));
+ 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);
+ g_warning("Diameter: Packet too short: %u bytes less than min size (%lu bytes))",
+ pktLength, (unsigned long)MIN_DIAMETER_SIZE);
BadPacket = TRUE;
}
BadPacket = TRUE;
}
- if (check_col(pinfo->fd, COL_INFO)) {
- col_add_fstr(pinfo->fd, COL_INFO,
- "%s%s%s: %s vendor=%s (hop-id=%d) (end-id=%d) RPE=%d%d%d",
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_fstr(pinfo->cinfo, COL_INFO,
+ "%s%s%s%s%s vendor=%s (hop-id=%u) (end-id=%u) RPE=%d%d%d",
(BadPacket)?"***** Bad Packet!: ":"",
(flags & DIAM_FLAGS_P)?"Proxyable ":"",
(flags & DIAM_FLAGS_E)?" Error":"",
- commandString, vendorString,
+ ((BadPacket ||
+ (flags & (DIAM_FLAGS_P|DIAM_FLAGS_E))) ?
+ ": " : ""),
+ commandString, vendorName,
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);
+ ti = proto_tree_add_item(tree, proto_diameter, tvb, offset,
+ MAX(pktLength,MIN_DIAMETER_SIZE), FALSE);
diameter_tree = proto_item_add_subtree(ti, ett_diameter);
/* Version */
/* Vendor Id */
proto_tree_add_uint_format(diameter_tree,hf_diameter_vendor_id,
- tvb, offset, 4, dh.vendorId, "Vendor-Id: %s", vendorString);
+ tvb, offset, 4, dh.vendorId, "Vendor-Id: %s", vendorName);
offset += 4;
/* Hop-by-hop Identifier */
/* Update the lengths */
avplength= pktLength - sizeof(e_diameterhdr);
-
- avp_tvb = tvb_new_subset(tvb, offset, -1, avplength);
+
+ avp_tvb = tvb_new_subset(tvb, offset, avplength, avplength);
avptf = proto_tree_add_text(diameter_tree,
- tvb, offset, tvb_length(tvb),
+ tvb, offset, avplength,
"Attribute Value Pairs");
-
+
avp_tree = proto_item_add_subtree(avptf,
ett_diameter_avp);
if (avp_tree != NULL) {
dissect_avps( avp_tvb, pinfo, avp_tree);
}
+ return;
}
-} /* dissect_diameter */
+} /* dissect_diameter_common */
+
+
+static guint
+get_diameter_pdu_len(tvbuff_t *tvb, int offset)
+{
+ /* Get the length of the Diameter packet. */
+ return tvb_get_ntoh24(tvb, offset + 1);
+}
+
+static int
+dissect_diameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!check_diameter(tvb))
+ return 0;
+ dissect_diameter_common(tvb, pinfo, tree);
+ return tvb_length(tvb);
+}
+
+static int
+dissect_diameter_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (!check_diameter(tvb))
+ return 0;
+ tcp_dissect_pdus(tvb, pinfo, tree, gbl_diameter_desegment, 4,
+ get_diameter_pdu_len, dissect_diameter_common);
+ return tvb_length(tvb);
+} /* dissect_diameter_tcp */
/*
* Call the mip_dissector, after saving our pinfo variables
mip_tvb = tvb_new_subset(tvb, offset,
MIN(length, tvb_length(tvb)-offset),
length);
-
+
/* The contained packet is a MIP registration request;
dissect it with the MIP dissector. */
- col_set_writable(pinfo->fd, FALSE);
+ col_set_writable(pinfo->cinfo, FALSE);
/* Also, save the current values of the addresses, and restore
them when we're finished dissecting the contained packet, so
gchar avpNameString[64];
gchar *valstr;
guint32 vendorId=0;
- gchar vendorString[64];
+ gchar vendorName[64];
int hdrLength;
int fixAmt;
proto_tree *avpi_tree;
- size_t offset = 0 ;
- char dataBuffer[4096];
+ size_t offset = 0;
tvbuff_t *group_tvb;
- tvbuff_t *mip_tvb;
proto_tree *group_tree;
proto_item *grouptf;
proto_item *avptf;
guint8 flags;
proto_item *tf;
proto_tree *flags_tree;
-
+
gint32 packetLength;
size_t avpDataLength;
int avpType;
/* 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);
+ g_warning("Diameter: AVP Payload too short: %d bytes less than min size (%ld bytes))",
+ packetLength, (long)MIN_AVP_SIZE);
BadPacket = TRUE;
/* Don't even bother trying to parse a short packet. */
return;
}
-
+
/* Copy our header */
tvb_memcpy(tvb, (guint8*) &avph, offset, MIN((long)sizeof(avph),packetLength));
-
+
/* Fix the byte ordering */
- avph.avp_code = ntohl(avph.avp_code);
- avph.avp_flagsLength = ntohl(avph.avp_flagsLength);
-
+ avph.avp_code = g_ntohl(avph.avp_code);
+ avph.avp_flagsLength = g_ntohl(avph.avp_flagsLength);
+
flags = (avph.avp_flagsLength & 0xff000000) >> 24;
avpLength = avph.avp_flagsLength & 0x00ffffff;
-
+
/* Set up our flags string */
- if (check_col(pinfo->fd, COL_INFO) || avp_tree) {
+ if (check_col(pinfo->cinfo, COL_INFO) || avp_tree) {
flagstr[0]=0;
for (i = 0; i < 8; i++) {
bpos = 1 << i;
/* Dissect our vendor id if it exists and set hdr length */
if (flags & AVP_FLAGS_V) {
- vendorId = ntohl(avph.avp_vendorId);
+ vendorId = g_ntohl(avph.avp_vendorId);
/* Vendor id */
hdrLength = sizeof(e_avphdr);
} else {
/* No vendor */
- hdrLength = sizeof(e_avphdr) -
+ hdrLength = sizeof(e_avphdr) -
sizeof(guint32);
vendorId = 0;
}
if (vendorId) {
- strcpy(vendorString,
- diameter_vendor_to_str(vendorId));
+ strcpy(vendorName,
+ diameter_vendor_to_str(vendorId, TRUE));
} else {
- vendorString[0]='\0';
+ vendorName[0]='\0';
}
/* Check for bad length */
- if (avpLength < MIN_AVP_SIZE ||
+ 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);
+ g_warning("Diameter: AVP payload size invalid: avp_length: %ld bytes, "
+ "min: %ld bytes, packetLen: %d",
+ (long)avpLength, (long)MIN_AVP_SIZE,
+ packetLength);
BadPacket = TRUE;
}
" resFl=0x%x",
flags, AVP_FLAGS_RESERVED);
/* For now, don't set bad packet, since I'm accidentally setting a wrong bit */
- // BadPacket = TRUE;
+ /* 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) ",
}
/* Make avp Name & type */
- strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code), TypeValues,
+ strcpy(avpTypeString, val_to_str(diameter_avp_get_type(avph.avp_code,vendorId),
+ TypeValues,
"Unknown-Type: 0x%08x"));
- strcpy(avpNameString, diameter_avp_get_name(avph.avp_code));
+ strcpy(avpNameString, diameter_avp_get_name(avph.avp_code, vendorId));
avptf = proto_tree_add_text(avp_tree, tvb,
offset, avpLength + fixAmt,
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);
if (flags & AVP_FLAGS_V) {
proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_vendor_id,
- tvb, offset, 4, vendorId, vendorString);
+ tvb, offset, 4, vendorId, vendorName);
offset += 4;
}
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)");
+ tvb, offset, tvb_length(tvb) - offset,
+ tvb_get_ptr(tvb, offset, tvb_length(tvb) - offset),
+ "Bad AVP (Suspect Data Not Dissected)");
return;
}
- avpType=diameter_avp_get_type(avph.avp_code);
- tvb_memcpy(tvb, (guint8*) dataBuffer, offset, MIN(4095,avpDataLength));
-
-
+ avpType=diameter_avp_get_type(avph.avp_code,vendorId);
+
switch(avpType) {
case DIAMETER_GROUPED:
sprintf(buffer, "%s Grouped AVPs", avpNameString);
grouptf = proto_tree_add_text(avpi_tree,
tvb, offset, tvb_length(tvb),
buffer);
-
+
group_tree = proto_item_add_subtree(grouptf,
ett_diameter_avp);
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);
+ {
+ const guint8 *data;
+
+ data = tvb_get_ptr(tvb, offset, avpDataLength);
+ proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
+ tvb, offset, avpDataLength, data,
+ "Identity: %*.*s",
+ (int)avpDataLength,
+ (int)avpDataLength, data);
+ }
break;
case DIAMETER_UTF8STRING:
- proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
- tvb, offset, avpDataLength, dataBuffer,
- "UTF8String: %*.*s", (int)avpDataLength, (int)avpDataLength,
- dataBuffer);
+ {
+ const guint8 *data;
+
+ data = tvb_get_ptr(tvb, offset, avpDataLength);
+ proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
+ tvb, offset, avpDataLength, data,
+ "UTF8String: %*.*s",
+ (int)avpDataLength,
+ (int)avpDataLength, data);
+ }
break;
case DIAMETER_IP_ADDRESS:
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));
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
+ tvb, offset, avpDataLength, FALSE);
} 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]));
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v6addr,
+ tvb, offset, avpDataLength, FALSE);
} else {
proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength, dataBuffer,
- "Error! Bad Address Length");
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "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: %d", data );
+ if (avpDataLength == 4) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int32,
+ tvb, offset, avpDataLength, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Integer32 Length");
}
break;
case DIAMETER_UNSIGNED32:
- {
+ if (avpDataLength == 4) {
guint32 data;
- memcpy(&data, dataBuffer, 4);
- data=ntohl(data);
+ data = tvb_get_ntohl(tvb, offset);
proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "Value: 0x%08x (%u)", data,
- data );
+ tvb, offset, avpDataLength, data,
+ "Value: 0x%08x (%u)", data, data);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Unsigned32 Length");
}
break;
case DIAMETER_INTEGER64:
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64, tvb, offset, 8, FALSE);
+ if (avpDataLength == 8) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64,
+ tvb, offset, 8, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Integer64 Length");
+ }
break;
case DIAMETER_UNSIGNED64:
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64, tvb, offset, 8, FALSE);
+ if (avpDataLength == 8) {
+ proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64,
+ tvb, offset, 8, FALSE);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Unsigned64 Length");
+ }
break;
case DIAMETER_TIME:
- valstr=diameter_time_to_string(dataBuffer);
+ if (avpDataLength == 4) {
+ nstime_t data;
+ gchar buffer[64];
+ struct tm *ltp;
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength, dataBuffer, "Time: %s", valstr);
+ data.secs = tvb_get_ntohl(tvb, offset);
+ data.secs -= NTP_TIME_DIFF;
+ data.nsecs = 0;
+
+ ltp = localtime(&data.secs);
+ strftime(buffer, 64,
+ "%a, %d %b %Y %H:%M:%S %z", ltp);
+
+ proto_tree_add_time_format(avpi_tree, hf_diameter_avp_data_time,
+ tvb, offset, avpDataLength, &data,
+ "Time: %s", buffer);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Time Length");
+ }
break;
case DIAMETER_ENUMERATED:
- {
+ if (avpDataLength == 4) {
guint32 data;
-
- memcpy(&data, dataBuffer, 4);
- data = ntohl(data);
- valstr = diameter_avp_get_value(avph.avp_code, data);
+
+ data = tvb_get_ntohl(tvb, offset);
+ valstr = diameter_avp_get_value(avph.avp_code, vendorId, data);
proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "Value: 0x%08x (%u): %s", data, data, valstr);
+ tvb, offset, avpDataLength, data,
+ "Value: 0x%08x (%u): %s", data,
+ data, valstr);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Enumerated Length");
}
break;
case DIAMETER_VENDOR_ID:
- {
+ if (avpDataLength == 4) {
guint32 data;
-
- memcpy(&data, dataBuffer, 4);
- data = ntohl(data);
- valstr = diameter_vendor_to_str(data);
+
+ data = tvb_get_ntohl(tvb, offset);
+ valstr = diameter_vendor_to_str(data, TRUE);
proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "%s (0x%08x)", valstr, data);
+ tvb, offset, avpDataLength, data,
+ "Vendor ID: %s (0x%08x)", valstr,
+ data);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Vendor ID Length");
}
break;
case DIAMETER_APPLICATION_ID:
- {
+ if (avpDataLength == 4) {
guint32 data;
-
- memcpy(&data, dataBuffer, 4);
- data = ntohl(data);
+
+ data = tvb_get_ntohl(tvb, offset);
valstr = diameter_app_to_str(data);
proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "%s (0x%08x)", valstr, data);
+ tvb, offset, avpDataLength, data,
+ "Application ID: %s (0x%08x)",
+ valstr, data);
+ } else {
+ proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Error! Bad Application ID Length");
}
break;
case DIAMETER_MIP_REG_REQ:
-
- /* Make a new tvb */
safe_dissect_mip(tvb, pinfo, avpi_tree, offset, avpDataLength);
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");
+ tvb, offset, avpDataLength,
+ tvb_get_ptr(tvb, offset, avpDataLength),
+ "Hex Data Highlighted Below");
break;
-
+
} /* switch type */
} /* avpi_tree != null */
offset += (avpLength - hdrLength);
static int Initialized=FALSE;
static int TcpPort=0;
static int SctpPort=0;
-
- if (Initialized) {
- dissector_delete("tcp.port", TcpPort, dissect_diameter);
- dissector_delete("sctp.port", SctpPort, dissect_diameter);
- } else {
+ static dissector_handle_t diameter_tcp_handle;
+ static dissector_handle_t diameter_handle;
+
+ if (!Initialized) {
+ diameter_tcp_handle = new_create_dissector_handle(dissect_diameter_tcp,
+ proto_diameter);
+ diameter_handle = new_create_dissector_handle(dissect_diameter,
+ proto_diameter);
Initialized=TRUE;
+ } else {
+ dissector_delete("tcp.port", TcpPort, diameter_tcp_handle);
+ dissector_delete("sctp.port", SctpPort, diameter_handle);
}
/* set port for future deletes */
TcpPort=gbl_diameterTcpPort;
SctpPort=gbl_diameterSctpPort;
- strcpy(gbl_diameterString, "Diameter Protocol");
-
/* g_warning ("Diameter: Adding tcp dissector to port %d",
gbl_diameterTcpPort); */
- dissector_add("tcp.port", gbl_diameterTcpPort, dissect_diameter,
- proto_diameter);
- dissector_add("sctp.port", gbl_diameterSctpPort,
- dissect_diameter, proto_diameter);
+ dissector_add("tcp.port", gbl_diameterTcpPort, diameter_tcp_handle);
+ dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
}
/* registration with the filtering engine */
{ &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 }},
{ "Hop-by-Hop Identifier", "diameter.hopbyhopid", FT_UINT32,
BASE_HEX, NULL, 0x0, "", HFILL }},
{ &hf_diameter_endtoendid,
- { "End-to-End Identifier", "diameter.endtoendid", FT_UINT32,
+ { "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 }},
{ "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_UINT64, BASE_DEC,
+ { "Value","diameter.avp.data.uint64", FT_UINT64, BASE_DEC,
NULL, 0x0, "", HFILL }},
{ &hf_diameter_avp_data_int64,
- { "AVP Data","diameter.avp.data.int64", FT_INT64, BASE_DEC,
+ { "Value","diameter.avp.data.int64", FT_INT64, BASE_DEC,
NULL, 0x0, "", HFILL }},
{ &hf_diameter_avp_data_uint32,
- { "AVP Data","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
+ { "Value","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,
+ { "Value","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,
+ { "Value","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
NULL, 0x0, "", HFILL }},
-
{ &hf_diameter_avp_data_string,
- { "AVP Data","diameter.avp.data.string", FT_STRING, BASE_NONE,
+ { "Value","diameter.avp.data.string", FT_STRING, BASE_NONE,
NULL, 0x0, "", HFILL }},
{ &hf_diameter_avp_data_v4addr,
- { "AVP Data","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
+ { "IPv4 Address","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
NULL, 0x0, "", HFILL }},
{ &hf_diameter_avp_data_v6addr,
- { "AVP Data","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
+ { "IPv6 Address","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
NULL, 0x0, "", HFILL }},
{ &hf_diameter_avp_data_time,
- { "AVP Data","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
+ { "Time","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
NULL, 0x0, "", HFILL }},
};
&ett_diameter_avpinfo
};
module_t *diameter_module;
+ gchar *default_diameterDictionary;
- proto_diameter = proto_register_protocol (gbl_diameterString,
- "Diameter", "diameter");
+ proto_diameter = proto_register_protocol ("Diameter Protocol", "Diameter", "diameter");
proto_register_field_array(proto_diameter, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
/*
* Build our default dictionary filename
*/
- if (! gbl_diameterDictionary) {
- gbl_diameterDictionary = (gchar *) g_malloc(strlen(get_datafile_dir()) +
- 1 + strlen(DICT_FN) + 1); /* slash + fn + null */
- sprintf(gbl_diameterDictionary, "%s" G_DIR_SEPARATOR_S "%s",
- get_datafile_dir(), DICT_FN );
- }
- /* Now register its preferences so it can be changed. */
+ default_diameterDictionary = get_datafile_path(DICT_FN);
+
+ /*
+ * Now register the dictionary filename as a preference,
+ * so it can be changed.
+ */
+ gbl_diameterDictionary = default_diameterDictionary;
prefs_register_string_preference(diameter_module, "dictionary.name",
"Diameter XML Dictionary",
"Set the dictionary used for Diameter messages",
&gbl_diameterDictionary);
+ /*
+ * We don't need the default dictionary, so free it (a copy was made
+ * of it in "gbl_diameterDictionary" by
+ * "prefs_register_string_preference()").
+ */
+ g_free(default_diameterDictionary);
+
+ /* Desegmentation */
+ prefs_register_bool_preference(diameter_module, "desegment",
+ "Desegment all Diameter messages\nspanning multiple TCP segments",
+ "Whether the Diameter dissector should desegment all messages spanning multiple TCP segments",
+ &gbl_diameter_desegment);
+ /* Allow zero as valid application ID */
+ prefs_register_bool_preference(diameter_module, "allow_zero_as_app_id",
+ "Allow 0 as valid application ID",
+ "If set, the value 0 (zero) can be used as a valid "
+ "application ID. This is used in experimental cases.",
+ &allow_zero_as_app_id);
+ /* Register some preferences we no longer support, so we can report
+ them as obsolete rather than just illegal. */
+ prefs_register_obsolete_preference(diameter_module, "udp.port");
+ prefs_register_obsolete_preference(diameter_module, "command_in_header");
} /* proto_register_diameter */