aboutsummaryrefslogtreecommitdiffstats
path: root/packet-diameter.c
diff options
context:
space:
mode:
authorGilbert Ramirez <gram@alumni.rice.edu>2004-07-18 18:06:47 +0000
committerGilbert Ramirez <gram@alumni.rice.edu>2004-07-18 18:06:47 +0000
commit669db206cb1f270046ad400fff7655e20c63e723 (patch)
tree4eff24a2e16c8963e497e1fc575f35e6af59bd26 /packet-diameter.c
parentae46c27a38700af669ef907491081f09df6f6b2c (diff)
Move dissectors to epan/dissectors directory.
Also move ncp222.py, x11-fields, process-x11-fields.pl, make-reg-dotc, and make-reg-dotc.py. Adjust #include lines in files that include packet-*.h files. svn path=/trunk/; revision=11410
Diffstat (limited to 'packet-diameter.c')
-rw-r--r--packet-diameter.c1965
1 files changed, 0 insertions, 1965 deletions
diff --git a/packet-diameter.c b/packet-diameter.c
deleted file mode 100644
index acb9466014..0000000000
--- a/packet-diameter.c
+++ /dev/null
@@ -1,1965 +0,0 @@
-/* packet-diameter.c
- * Routines for Diameter packet disassembly
- *
- * $Id$
- *
- * Copyright (c) 2001 by David Frascone <dave@frascone.com>
- *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
- * Copyright 1998 Gerald Combs
- *
- * 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.
- * References:
- * 2004-03-11
- * http://www.ietf.org/rfc/rfc3588.txt
- * http://www.iana.org/assignments/radius-types
- * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-cc-03.txt
- * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-nasreq-14.txt
- * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-mobileip-16.txt
- * http://www.ietf.org/internet-drafts/draft-ietf-aaa-diameter-sip-app-01.txt
- * http://www.ietf.org/html.charters/aaa-charter.html
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <glib.h>
-#include <epan/filesystem.h>
-#include "xmlstub.h"
-#include <epan/packet.h>
-#include <epan/resolv.h>
-#include <epan/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 */
-
-/* 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 */
- DIAMETER_MIP_REG_REQ, /* OctetString */
- DIAMETER_VENDOR_ID, /* Integer32 */
- DIAMETER_APPLICATION_ID,
- DIAMETER_URI, /* OctetString */
- DIAMETER_SESSION_ID /* OctetString */
-
-} diameterDataType;
-
-
-static value_string TypeValues[]={
- { DIAMETER_OCTET_STRING, "OctetString" },
- { DIAMETER_INTEGER32, "Integer32" },
- { DIAMETER_INTEGER64, "Integer64" },
- { DIAMETER_UNSIGNED32, "Unsigned32" },
- { DIAMETER_UNSIGNED64, "Unsigned64" },
- { DIAMETER_FLOAT32, "Float32" },
- { DIAMETER_FLOAT64, "Float64" },
- { DIAMETER_FLOAT128, "Float128" },
- { DIAMETER_GROUPED, "Grouped" },
- { DIAMETER_IP_ADDRESS, "IpAddress" },
- { DIAMETER_TIME, "Time" },
- { DIAMETER_UTF8STRING, "UTF8String" },
- { DIAMETER_IDENTITY, "DiameterIdentity" },
- { DIAMETER_ENUMERATED, "Enumerated" },
- { DIAMETER_IP_FILTER_RULE, "IPFilterRule" },
- { DIAMETER_QOS_FILTER_RULE, "QOSFilterRule" },
- { DIAMETER_MIP_REG_REQ, "MIPRegistrationRequest"},
- { DIAMETER_VENDOR_ID, "VendorId"},
- { DIAMETER_APPLICATION_ID, "AppId"},
- { DIAMETER_URI, "DiameterURI"},
- { DIAMETER_SESSION_ID, "Session-Id"},
-
- {0, (char *)NULL}
-};
-
-typedef struct value_name {
- guint32 value;
- gchar *name;
- struct value_name *next;
-} ValueName;
-
-typedef struct old_avp_info {
- guint32 code;
- gchar *name;
- diameterDataType type;
- value_string *values;
-} oldAvpInfo;
-
-typedef struct avp_info {
- guint32 code;
- gchar *name;
- gchar *vendorName;
- diameterDataType type;
- ValueName *values;
- struct avp_info *next;
-} avpInfo;
-
-typedef struct command_code {
- guint32 code;
- gchar *name;
- gchar *vendorName;
- struct command_code *next;
-} CommandCode;
-
-typedef struct vendor_id {
- guint32 id;
- gchar *name;
- gchar *longName;
- struct vendor_id *next;
-} VendorId;
-
-typedef struct application_id {
- guint32 id;
- gchar *name;
- struct application_id *next;
-} ApplicationId;
-
-static avpInfo *avpListHead=NULL;
-static VendorId *vendorListHead=NULL;
-static CommandCode *commandListHead=NULL;
-static ApplicationId *ApplicationIdHead=NULL;
-
-
-#include "packet-diameter-defs.h"
-
-#define NTP_TIME_DIFF (2208988800UL)
-
-#define TCP_PORT_DIAMETER 1812
-#define SCTP_PORT_DIAMETER 1812
-
-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_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_T = -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_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;
-static int hf_diameter_avp_data_v6addr = -1;
-static int hf_diameter_avp_data_time = -1;
-static int hf_diameter_avp_session_id = -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 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;
-
-/* Supress console output at unknown AVP:s,Flags etc */
-static gboolean suppress_console_output = TRUE;
-
-#define DICT_FN "diameter/dictionary.xml"
-static gchar *gbl_diameterDictionary;
-
-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;
-
-/* Diameter Header Flags */
-/* RPrrrrrrCCCCCCCCCCCCCCCCCCCCCCCC */
-#define DIAM_FLAGS_R 0x80
-#define DIAM_FLAGS_P 0x40
-#define DIAM_FLAGS_E 0x20
-#define DIAM_FLAGS_T 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 0x0f
-
-#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))
-
-static void dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
-
-
-/*
- * This routine will do a push-parse of the passed in
- * filename. This was taken almost verbatum from
- * the xmlsoft examples.
- */
-static xmlDocPtr
-xmlParseFilePush( char *filename, int checkValid) {
- FILE *f;
- xmlDocPtr doc=NULL;
- int valid=0;
- 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) {
- report_open_failure(filename, errno, FALSE);
- return NULL;
- }
-
- res = fread(chars, 1, 4, f);
- if (res > 0) {
- ctxt = XmlStub.xmlCreatePushParserCtxt(NULL, NULL,
- chars, res, filename);
- while ((res = fread(chars, 1, size-1, f)) > 0) {
- XmlStub.xmlParseChunk(ctxt, chars, res, 0);
- }
- XmlStub.xmlParseChunk(ctxt, chars, 0, 1);
- doc = ctxt->myDoc;
- valid=ctxt->valid;
- XmlStub.xmlFreeParserCtxt(ctxt);
- }
- fclose(f);
-
- /* Check valid */
- if (!valid) {
- report_failure( "Error! Invalid xml in %s! Failed DTD check!",
- filename);
- return NULL;
- }
- return doc;
-} /* xmlParseFilePush */
-
-/*
- * This routine will add a static avp to the avp list. It is
- * only called when the XML dictionary fails to load properly.
- */
-static int
-addStaticAVP(int code, gchar *name, diameterDataType type, value_string *values)
-{
- avpInfo *entry;
- ValueName *vEntry=NULL;
- int i;
-
- /* Parse our values array, if we have one */
- if (values) {
- for (i=0; values[i].strptr != NULL; i++) {
- ValueName *ve = NULL;
-
- ve = g_malloc(sizeof(ValueName));
- ve->name = strdup(values[i].strptr);
- ve->value = values[i].value;
- ve->next = vEntry;
- vEntry = ve;
- }
- } /* if values */
-
- /* And, create the entry */
- entry = (avpInfo *)g_malloc(sizeof(avpInfo));
- entry->name = g_strdup(name);
- entry->code = code;
- entry->vendorName = NULL;
- entry->type = type;
- entry->values = vEntry;
- if (vEntry)
- entry->type = DIAMETER_ENUMERATED;
-
- /* And, add it to the list */
- entry->next = avpListHead;
- avpListHead = entry;
-
- return (0);
-
-} /* addStaticAVP */
-
-/*
- * This routine will parse an XML avp entry, and add it to our
- * avp list. If any values are present in the avp, it will
- * add them too.
- */
-static int
-xmlParseAVP(xmlNodePtr cur)
-{
- char *name=NULL, *description=NULL, *code=NULL, *mayEncrypt=NULL,
- *mandatory=NULL, *protected=NULL, *vendorBit=NULL, *vendorName = NULL,
- *constrained=NULL;
- char *type=NULL;
- avpInfo *entry;
- guint32 avpType=0;
- ValueName *vEntry=NULL;
- int i;
-
- /* First, get our properties */
- name = XmlStub.xmlGetProp(cur, "name");
- description = XmlStub.xmlGetProp(cur, "description");
- code = XmlStub.xmlGetProp(cur, "code");
- mayEncrypt = XmlStub.xmlGetProp(cur, "may-encrypt");
- mandatory = XmlStub.xmlGetProp(cur, "mandatory");
- protected = XmlStub.xmlGetProp(cur, "protected");
- vendorBit = XmlStub.xmlGetProp(cur, "vendor-bit");
- vendorName = XmlStub.xmlGetProp(cur, "vendor-id");
- constrained = XmlStub.xmlGetProp(cur, "constrained");
-
- cur = cur->xmlChildrenNode;
-
- while (cur != NULL ) {
- if (strcasecmp(cur->name, "type") == 0) {
- type = XmlStub.xmlGetProp(cur, "type-name");
- } 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) {
- report_failure( "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;
- } else if (strcasecmp(cur->name, "grouped") == 0) {
- /* WORK Recurse here for grouped AVPs */
- type = "grouped";
- }
- cur=cur->next;
- } /* while */
-
- /*
- * Check for the AVP Type.
- */
- if (type) {
- for (i = 0; TypeValues[i].strptr; i++) {
- if (!strcasecmp(type, TypeValues[i].strptr)) {
- avpType = TypeValues[i].value;
- break;
- }
- }
-
- if (TypeValues[i].strptr == NULL) {
- report_failure( "Invalid Type field in dictionary! avp %s (%s)", name, type);
- return (-1);
- }
- } else if (!vEntry) {
- report_failure("Missing type/enum field in dictionary avpName=%s",
- name);
- return (-1);
- }
-
- /* 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)
- entry->vendorName = g_strdup(vendorName);
- else
- entry->vendorName = NULL;
- entry->type = avpType;
- entry->values = vEntry;
- if (vEntry)
- entry->type = DIAMETER_INTEGER32;
-
- /* And, add it to the list */
- entry->next = avpListHead;
- avpListHead = entry;
-
- return (0);
-} /* xmlParseAVP */
-
-/*
- * This routine will add a command to the list of commands.
- */
-static int
-addCommand(int code, char *name, char *vendorId)
-{
- CommandCode *entry;
-
- /*
- * Allocate the memory required for the dictionary.
- */
- entry = (CommandCode *) g_malloc(sizeof (CommandCode));
-
- if (entry == NULL) {
- report_failure("Unable to allocate memory");
- return (-1);
- }
-
- /*
- * Allocate memory for the AVPName and copy the name to the
- * structure
- */
- entry->name = g_strdup(name);
- entry->code = code;
- if (vendorId)
- entry->vendorName = g_strdup(vendorId);
- else
- entry->vendorName = "None";
-
- /* Add the entry to the list */
- entry->next = commandListHead;
- commandListHead = entry;
-
- return 0;
-} /* addCommand */
-
-/*
- * This routine will parse the XML command, and add it to our
- * list of commands.
- */
-static int
-xmlParseCommand(xmlNodePtr cur)
-{
- char *name, *code, *vendorIdString;
-
- /*
- * Get the Attributes
- */
- name = XmlStub.xmlGetProp(cur, "name");
- code = XmlStub.xmlGetProp(cur, "code");
- if (!name || !code) {
- report_failure("Invalid command. Name or code missing!");
- return -1;
- }
- vendorIdString = XmlStub.xmlGetProp(cur, "vendor-id");
-
- if (!vendorIdString || !strcasecmp(vendorIdString, "None")) {
- vendorIdString = NULL;
- }
-
- return (addCommand(atoi(code), name, vendorIdString));
-} /* xmlParseCommand */
-
-/* This routine adds an application to the name<-> id table */
-static int
-dictionaryAddApplication(char *name, int id)
-{
- ApplicationId *entry;
-
- if (!name || (id < 0) || (id == 0 && !allow_zero_as_app_id)) {
- report_failure( "Diameter Error: Invalid application (name=%p, id=%d)",
- name, id);
- return (-1);
- } /* Sanity Checks */
-
- entry = g_malloc(sizeof(ApplicationId));
- if (!entry) {
- report_failure( "Unable to allocate memory");
- return (-1);
- }
-
- entry->name = g_strdup(name);
- entry->id = id;
-
- /* Add it to the list */
- entry->next = ApplicationIdHead;
- ApplicationIdHead = entry;
-
- return 0;
-} /* dictionaryAddApplication */
-
-/*
- * This routine will add a vendor to the vendors list
- */
-static int
-addVendor(int id, gchar *name, gchar *longName)
-{
- VendorId *vendor;
-
- /* add entry */
- vendor=g_malloc(sizeof(VendorId));
- if (!vendor) {
- return (-1);
- }
-
- vendor->id = id;
- vendor->name = g_strdup(name);
- vendor->longName = g_strdup(longName);
- vendor->next = vendorListHead;
- vendorListHead = vendor;
-
- return 0;
-} /* addVendor */
-
-/*
- * This routine will pars in a XML vendor entry.
- */
-static int
-xmlParseVendor(xmlNodePtr cur)
-{
- char *name=NULL, *code=NULL, *id=NULL;
-
- /* First, get our properties */
- id = XmlStub.xmlGetProp(cur, "vendor-id");
- name = XmlStub.xmlGetProp(cur, "name");
- code = XmlStub.xmlGetProp(cur, "code");
-
- if (!id || !name || !code) {
- report_failure( "Invalid vendor section. vendor-id, name, and code must be specified");
- return -1;
- }
-
- return (addVendor(atoi(code), id, name));
-} /* addVendor */
-
-/*
- * This routine will either parse in the base protocol, or an application.
- */
-static int
-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!!! */
- report_failure("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! */
- return -1;
- }
- }
-
-
- /*
- * Get segment values
- */
- cur = cur->xmlChildrenNode;
- while (cur != NULL) {
- if (strcasecmp(cur->name, "avp") == 0) {
- /* we have an avp!!! */
- xmlParseAVP(cur);
- } else if (strcasecmp(cur->name, "vendor") == 0) {
- /* we have a vendor */
- xmlParseVendor(cur);
- /* For now, ignore typedefn and text */
- } else if (strcasecmp(cur->name, "command") == 0) {
- /* Found a command */
- 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 */
- report_failure("Error! expecting an avp or a typedefn (got \"%s\")",
- cur->name);
- return (-1);
- }
- cur = cur->next;
- } /* while */
- return 0;
-} /* xmlDictionaryParseSegment */
-
-/*
- * The main xml parse routine. This will walk through an XML
- * dictionary that has been parsed by libxml.
- */
-static int
-xmlDictionaryParse(xmlNodePtr cur)
-{
- /* We should expect a base protocol, followed by multiple applications */
- while (cur != NULL) {
- if (strcasecmp(cur->name, "base") == 0) {
- /* Base protocol. Descend and parse */
- xmlDictionaryParseSegment(cur, 1);
- } else if (strcasecmp(cur->name, "application") == 0) {
- /* Application. Descend and parse */
- xmlDictionaryParseSegment(cur, 0);
- } else if (strcasecmp(cur->name, "text") == 0) {
- /* Ignore text */
- } else if (strcasecmp(cur->name, "comment") == 0) {
- /* Ignore text */
- } else {
- report_failure( "Diameter: XML Expecting a base or an application (got \"%s\")",
- cur->name);
- return (-1);
- }
- cur = cur->next;
- }
-
- return 0;
-
-} /* xmlDictionaryParse */
-
-/*
- * This routine will call libxml to parse in the dictionary.
- */
-static int
-loadXMLDictionary(void)
-{
- xmlDocPtr doc;
- xmlNodePtr cur;
-
- /*
- * build an XML tree from a the file;
- */
- XmlStub.xmlKeepBlanksDefault(0); /* Strip leading and trailing blanks */
- XmlStub.xmlSubstituteEntitiesDefault(1); /* Substitute entities automagically */
- doc = xmlParseFilePush(gbl_diameterDictionary, 1); /* Parse the XML (do validity checks)*/
-
- /* Check for invalid xml */
- if (doc == NULL) {
- report_failure("Diameter: Unable to parse xmldictionary %s",
- gbl_diameterDictionary);
- return -1;
- }
-
- /*
- * Check the document is of the right kind
- */
- cur = XmlStub.xmlDocGetRootElement(doc);
- if (cur == NULL) {
- report_failure("Diameter: Error: \"%s\": empty document",
- gbl_diameterDictionary);
- XmlStub.xmlFreeDoc(doc);
- return -1;
- }
- if (XmlStub.xmlStrcmp(cur->name, (const xmlChar *) "dictionary")) {
- report_failure("Diameter: Error: \"%s\": document of the wrong type, root node != dictionary",
- gbl_diameterDictionary);
- 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(cur->xmlChildrenNode) != 0) {
- /* Error has already been printed */
- return -1;
- }
-
- /* Once we're done parsing, free up the xml memory */
- XmlStub.xmlFreeDoc(doc);
-
- return 0;
-
-} /* loadXMLDictionary */
-
-/*
- * Fallback routine. In the event of ANY error when loading the XML
- * dictionary, this routine will populate the new avp list structures
- * with the old static data from packet-diameter-defs.h
- */
-static void
-initializeDictionaryDefaults(void)
-{
- int i;
-
- /* Add static vendors to list */
- for(i=0; diameter_vendor_specific_vendors[i].strptr; i++) {
- addVendor(diameter_vendor_specific_vendors[i].value,
- diameter_vendor_specific_vendors[i].strptr,
- diameter_vendor_specific_vendors[i].strptr);
- }
- /* Add static commands to list. */
- for(i=0; diameter_command_code_vals[i].strptr; i++) {
- addCommand(diameter_command_code_vals[i].value,
- diameter_command_code_vals[i].strptr, NULL);
- }
-
- /* Add static AVPs to list */
- for (i=0; old_diameter_avps[i].name; i++) {
- addStaticAVP(old_diameter_avps[i].code,
- old_diameter_avps[i].name,
- old_diameter_avps[i].type,
- old_diameter_avps[i].values);
- }
-
-} /* initializeDictionaryDefaults */
-
-/*
- * This routine will attempt to load the XML dictionary, and on
- * failure, will call initializeDictionaryDefaults to load in
- * our static dictionary.
- */
-static void
-initializeDictionary(void)
-{
- /*
- * 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.
- */
- if (loadLibXML() ||
- (loadXMLDictionary() != 0)) {
- /* Something failed. Use the static dictionary */
- report_failure("Diameter: Using static dictionary! (Unable to use XML)");
- initializeDictionaryDefaults();
- }
-} /* initializeDictionary */
-
-
-
-/*
- * These routines manipulate the diameter structures.
- */
-
-/* return vendor string, based on the id */
-static gchar *
-diameter_vendor_to_str(guint32 vendorId, gboolean longName) {
- VendorId *probe;
- static gchar buffer[64];
-
- for (probe=vendorListHead; probe; probe=probe->next) {
- if (vendorId == probe->id) {
- if (longName)
- return probe->longName;
- else
- return probe->name;
- }
- }
-
- snprintf(buffer, sizeof(buffer),
- "Vendor 0x%08x", vendorId);
- return buffer;
-} /*diameter_vendor_to_str */
-
-/* return command string, based on the code */
-static gchar *
-diameter_command_to_str(guint32 commandCode, guint32 vendorId)
-{
- CommandCode *probe;
- static gchar buffer[64];
- gchar *vendorName=NULL;
-
- 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;
- }
- }
- }
- }
-
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: Unable to find name for command code 0x%08x, Vendor \"%u\"!",
- commandCode, vendorId);
- snprintf(buffer, sizeof(buffer),
- "Cmd-0x%08x", commandCode);
-
- return buffer;
-}/*diameter_command_to_str */
-
-/* return application string, based on the id */
-static gchar *
-diameter_app_to_str(guint32 vendorId) {
- ApplicationId *probe;
- static gchar buffer[64];
-
- for (probe=ApplicationIdHead; probe; probe=probe->next) {
- if (vendorId == probe->id) {
- return probe->name;
- }
- }
-
- snprintf(buffer, sizeof(buffer),
- "AppId 0x%08x", vendorId);
- return buffer;
-} /*diameter_app_to_str */
-
-/* return an avp type, based on the code */
-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) {
-
- 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 */
- if ( suppress_console_output == FALSE )
- 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, 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) {
- 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;
- }
- }
- }
- if ( suppress_console_output == FALSE )
- 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 vendorId, guint32 avpValue)
-{
- 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) {
- 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;
- }
- }
- return "(Unknown value)";
- }
- } else {
- if (!probe->vendorName) {
- ValueName *vprobe;
- for(vprobe=probe->values; vprobe; vprobe=vprobe->next) {
- if (avpValue == vprobe->value) {
- return vprobe->name;
- }
- }
- return "(Unknown value)";
- }
- }
- }
- }
- /* We didn't find the avp */
- return "(Unknown AVP)";
-} /* diameter_avp_get_value */
-
-
-/* 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_common(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;
- int 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], vendorName[64];
- gint i;
- guint bpos;
- static int initialized=FALSE;
-
- /*
- * Only parse in dictionary if there are diameter packets to
- * dissect.
- */
- if (!initialized) {
- /* Read in our dictionary, if it exists. */
- initializeDictionary();
- initialized=TRUE;
- }
-
- /* Make entries in Protocol column and Info column on summary display */
- 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 = 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(vendorName,
- diameter_vendor_to_str(dh.vendorId, TRUE));
- } else {
- strcpy(vendorName, "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->cinfo, 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, 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) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: Packet too short: %u bytes less than min size (%lu bytes))",
- pktLength, (unsigned long)MIN_DIAMETER_SIZE);
- BadPacket = TRUE;
- }
-
- /* And, check our reserved flags/version */
- if ((flags & DIAM_FLAGS_RESERVED) ||
- (version != 1)) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: Bad packet: Bad Flags(0x%x) or Version(%u)",
- flags, version);
- BadPacket = TRUE;
- }
-
- 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":"",
- ((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,
- MAX(pktLength,MIN_DIAMETER_SIZE), 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_T, 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", vendorName);
- 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, avplength, avplength);
- avptf = proto_tree_add_text(diameter_tree,
- 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_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
- * so it doesn't write to our column display.
- */
-static void
-safe_dissect_mip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
- size_t offset, size_t length)
-{
- static dissector_handle_t mip_handle;
- static int mipInitialized=FALSE;
- tvbuff_t *mip_tvb;
- address save_dl_src;
- address save_dl_dst;
- address save_net_src;
- address save_net_dst;
- address save_src;
- address save_dst;
- gboolean save_in_error_pkt;
-
- if (!mipInitialized) {
- mip_handle = find_dissector("mip");
- mipInitialized=TRUE;
- }
-
- 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->cinfo, FALSE);
-
- /* Also, save the current values of the addresses, and restore
- them when we're finished dissecting the contained packet, so
- that the address columns in the summary don't reflect the
- contained packet, but reflect this packet instead. */
- save_dl_src = pinfo->dl_src;
- save_dl_dst = pinfo->dl_dst;
- save_net_src = pinfo->net_src;
- save_net_dst = pinfo->net_dst;
- save_src = pinfo->src;
- save_dst = pinfo->dst;
- save_in_error_pkt = pinfo->in_error_pkt;
-
- call_dissector(mip_handle, mip_tvb, pinfo, tree);
-
- /* Restore the "we're inside an error packet" flag. */
- pinfo->in_error_pkt = save_in_error_pkt;
- pinfo->dl_src = save_dl_src;
- pinfo->dl_dst = save_dl_dst;
- pinfo->net_src = save_net_src;
- pinfo->net_dst = save_net_dst;
- pinfo->src = save_src;
- pinfo->dst = save_dst;
-
-
-} /* safe_dissect_mip */
-
-/*
- * 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)
-{
- /* adds the attribute value pairs to the tree */
- e_avphdr avph;
- gchar avpTypeString[64];
- gchar avpNameString[64];
- gchar *valstr;
- guint32 vendorId=0;
- gchar vendorName[64];
- int hdrLength;
- int fixAmt;
- proto_tree *avpi_tree;
- size_t offset = 0;
- tvbuff_t *group_tvb;
- proto_tree *group_tree;
- proto_item *grouptf;
- proto_item *avptf;
- char buffer[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) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: AVP Payload too short: %d bytes less than min size (%ld bytes))",
- packetLength, (long)MIN_AVP_SIZE);
- BadPacket = TRUE;
- /* Don't even bother trying to parse a short packet. */
- return;
- }
-
- /* Copy our header */
- tvb_memcpy(tvb, (guint8*) &avph, offset, MIN((long)sizeof(avph),packetLength));
-
- /* Fix the byte ordering */
- avph.avp_code = g_ntohl(avph.avp_code);
- avph.avp_flagsLength = g_ntohl(avph.avp_flagsLength);
-
- flags = (avph.avp_flagsLength & 0xff000000) >> 24;
- avpLength = avph.avp_flagsLength & 0x00ffffff;
-
- /* Set up our flags string */
- if (check_col(pinfo->cinfo, COL_INFO) || avp_tree) {
- 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 = g_ntohl(avph.avp_vendorId);
- /* Vendor id */
- hdrLength = sizeof(e_avphdr);
- } else {
- /* No vendor */
- hdrLength = sizeof(e_avphdr) -
- sizeof(guint32);
- vendorId = 0;
- }
-
- if (vendorId) {
- strcpy(vendorName,
- diameter_vendor_to_str(vendorId, TRUE));
- } else {
- vendorName[0]='\0';
- }
-
- /* Check for bad length */
- if (avpLength < MIN_AVP_SIZE ||
- ((long)avpLength > packetLength)) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: AVP payload size invalid: avp_length: %ld bytes, "
- "min: %ld bytes, packetLen: %d",
- (long)avpLength, (long)MIN_AVP_SIZE,
- packetLength);
- BadPacket = TRUE;
- }
-
- /* Check for bad flags */
- if (flags & AVP_FLAGS_RESERVED) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: Invalid AVP: Reserved bit set. flags = 0x%x,"
- " resFl=0x%x",
- flags, AVP_FLAGS_RESERVED);
- /* For now, don't set bad packet, since I'm accidentally setting a wrong bit
- BadPacket = TRUE;
- */
- }
-
- /*
- * Compute amount of byte-alignment fix (Diameter AVPs are sent on 4 byte
- * boundries)
- */
- fixAmt = 4 - (avpLength % 4);
- if (fixAmt == 4) fixAmt = 0;
-
- /* shrink our packetLength */
- packetLength = packetLength - (avpLength + fixAmt);
-
- /* Check for out of bounds */
- if (packetLength < 0) {
- if ( suppress_console_output == FALSE )
- g_warning("Diameter: Bad AVP: Bad new length (%d bytes) ",
- packetLength);
- BadPacket = TRUE;
- }
-
- /* Make avp Name & type */
- 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, vendorId));
-
- avptf = proto_tree_add_text(avp_tree, tvb,
- offset, avpLength + fixAmt,
- "%s (%s) l:0x%x (%d bytes) (%d padded bytes)",
- avpNameString, avpTypeString, avpLength,
- avpLength, avpLength+fixAmt);
- avpi_tree = proto_item_add_subtree(avptf,
- ett_diameter_avpinfo);
-
- if (avpi_tree !=NULL) {
- /* Command Code */
- proto_tree_add_uint_format(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, vendorName);
- offset += 4;
- }
-
- avpDataLength = avpLength - hdrLength;
-
- /*
- * If we've got a bad packet, just highlight the data. Don't try
- * to parse it, and, don't move to next AVP.
- */
- if (BadPacket) {
- offset -= hdrLength;
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, tvb_length(tvb) - offset,
- tvb_get_ptr(tvb, offset, tvb_length(tvb) - offset),
- "Bad AVP (Suspect Data Not Dissected)");
- return;
- }
-
- avpType=diameter_avp_get_type(avph.avp_code,vendorId);
-
- 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:
- {
- const guint8 *data;
-
- data = tvb_get_ptr(tvb, offset, avpDataLength);
- proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
- tvb, offset, avpDataLength, data,
- "Identity: %*.*s",
- (int)avpDataLength,
- (int)avpDataLength, data);
- }
- break;
- case DIAMETER_UTF8STRING:
- {
- const guint8 *data;
-
- data = tvb_get_ptr(tvb, offset, avpDataLength);
- proto_tree_add_string_format(avpi_tree, hf_diameter_avp_data_string,
- tvb, offset, avpDataLength, data,
- "UTF8String: %*.*s",
- (int)avpDataLength,
- (int)avpDataLength, data);
- }
- break;
- case DIAMETER_IP_ADDRESS:
- if (avpDataLength == 4) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v4addr,
- tvb, offset, avpDataLength, FALSE);
- } else if (avpDataLength == 16) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_v6addr,
- tvb, offset, avpDataLength, FALSE);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Address Length");
- }
- break;
-
- case DIAMETER_INTEGER32:
- if (avpDataLength == 4) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int32,
- tvb, offset, avpDataLength, FALSE);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Integer32 Length");
- }
- break;
-
- case DIAMETER_UNSIGNED32:
- if (avpDataLength == 4) {
- guint32 data;
-
- data = tvb_get_ntohl(tvb, offset);
- proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "Value: 0x%08x (%u)", data, data);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Unsigned32 Length");
- }
- break;
-
- case DIAMETER_INTEGER64:
- if (avpDataLength == 8) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_int64,
- tvb, offset, 8, FALSE);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Integer64 Length");
- }
- break;
-
- case DIAMETER_UNSIGNED64:
- if (avpDataLength == 8) {
- proto_tree_add_item(avpi_tree, hf_diameter_avp_data_uint64,
- tvb, offset, 8, FALSE);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Unsigned64 Length");
- }
- break;
-
- case DIAMETER_TIME:
- if (avpDataLength == 4) {
- nstime_t data;
- gchar buffer[64];
- struct tm *ltp;
-
- 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;
-
- data = tvb_get_ntohl(tvb, offset);
- valstr = diameter_avp_get_value(avph.avp_code, vendorId, data);
- proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "Value: 0x%08x (%u): %s", data,
- data, valstr);
- } else {
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Error! Bad Enumerated Length");
- }
- break;
-
- case DIAMETER_VENDOR_ID:
- if (avpDataLength == 4) {
- guint32 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,
- "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;
-
- data = tvb_get_ntohl(tvb, offset);
- valstr = diameter_app_to_str(data);
- proto_tree_add_uint_format(avpi_tree, hf_diameter_avp_data_uint32,
- tvb, offset, avpDataLength, data,
- "Application ID: %s (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:
- safe_dissect_mip(tvb, pinfo, avpi_tree, offset, avpDataLength);
- break;
-
- case DIAMETER_SESSION_ID:
- proto_tree_add_item(avpi_tree, hf_diameter_avp_session_id,
- tvb, offset, avpDataLength, FALSE);
- break;
-
- default:
- case DIAMETER_OCTET_STRING:
- proto_tree_add_bytes_format(avpi_tree, hf_diameter_avp_data_bytes,
- tvb, offset, avpDataLength,
- tvb_get_ptr(tvb, offset, avpDataLength),
- "Hex Data Highlighted Below");
- break;
-
- } /* switch type */
- } /* avpi_tree != null */
- offset += (avpLength - hdrLength);
- offset += fixAmt; /* fix byte alignment */
- } /* loop */
-} /* dissect_avps */
-
-
-
-void
-proto_reg_handoff_diameter(void)
-{
- static int Initialized=FALSE;
- static int TcpPort=0;
- static int SctpPort=0;
- 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;
-
- /* g_warning ("Diameter: Adding tcp dissector to port %d",
- gbl_diameterTcpPort); */
- dissector_add("tcp.port", gbl_diameterTcpPort, diameter_tcp_handle);
- dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
-}
-
-/* registration with the filtering engine */
-void
-proto_register_diameter(void)
-{
- 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_T,
- { "T(Potentially re-transmitted message)","diameter.flags.T", FT_BOOLEAN, 8, TFS(&flags_set_truth),DIAM_FLAGS_T,
- "", 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,
- { "Value","diameter.avp.data.uint64", FT_UINT64, BASE_DEC,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_int64,
- { "Value","diameter.avp.data.int64", FT_INT64, BASE_DEC,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_uint32,
- { "Value","diameter.avp.data.uint32", FT_UINT32, BASE_DEC,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_int32,
- { "Value","diameter.avp.data.int32", FT_INT32, BASE_DEC,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_bytes,
- { "Value","diameter.avp.data.bytes", FT_BYTES, BASE_NONE,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_string,
- { "Value","diameter.avp.data.string", FT_STRING, BASE_NONE,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_v4addr,
- { "IPv4 Address","diameter.avp.data.v4addr", FT_IPv4, BASE_NONE,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_v6addr,
- { "IPv6 Address","diameter.avp.data.v6addr", FT_IPv6, BASE_NONE,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_data_time,
- { "Time","diameter.avp.data.time", FT_ABSOLUTE_TIME, BASE_NONE,
- NULL, 0x0, "", HFILL }},
- { &hf_diameter_avp_session_id,
- { "Session ID","diameter.avp.session_id", FT_STRING, BASE_NONE,
- NULL, 0x0, "", HFILL }},
-
- };
- static gint *ett[] = {
- &ett_diameter,
- &ett_diameter_flags,
- &ett_diameter_avp,
- &ett_diameter_avp_flags,
- &ett_diameter_avpinfo
- };
- module_t *diameter_module;
- gchar *default_diameterDictionary;
-
- 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));
-
- /* Register a configuration option for port */
- diameter_module = prefs_register_protocol(proto_diameter,
- proto_reg_handoff_diameter);
- prefs_register_uint_preference(diameter_module, "tcp.port",
- "Diameter TCP Port",
- "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);
- /*
- * Build our default dictionary filename
- */
- 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. */
- /* Supress console output or not */
- prefs_register_bool_preference(diameter_module, "suppress_console_output",
- "Suppress console output for unknown AVP:s Flags etc.",
- "If console output for errors should be suppressed or not",
- &suppress_console_output);
- /* 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 */