Make both the Diameter-over-TCP and Diameter-over-SCTP dissectors

"new-style" dissectors, and have them reject packets that don't start
with a version number of 1, in the hopes that it'll be less likely to
try to dissect non-Diameter packets to/from port 1812 as Diameter and
thus less likely to spew out a bunch of warnings that cause users to ask
the Ethereal mailing lists what the problem is.

Use "tcp_dissect_pdus()" to handle Diameter-over-TCP.

svn path=/trunk/; revision=10165
This commit is contained in:
Guy Harris 2004-02-21 10:29:52 +00:00
parent 4a16df9517
commit 5e60a77f7d
1 changed files with 46 additions and 58 deletions

View File

@ -1,7 +1,7 @@
/* packet-diameter.c
* Routines for Diameter packet disassembly
*
* $Id: packet-diameter.c,v 1.60 2004/02/21 04:26:29 guy Exp $
* $Id: packet-diameter.c,v 1.61 2004/02/21 10:29:52 guy Exp $
*
* Copyright (c) 2001 by David Frascone <dave@frascone.com>
*
@ -41,6 +41,7 @@
#include <epan/resolv.h>
#include "report_err.h"
#include "prefs.h"
#include "packet-tcp.h"
#ifdef NEED_SNPRINTF_H
# include "snprintf.h"
@ -988,11 +989,25 @@ diameter_avp_get_value(guint32 avpCode, guint32 vendorId, guint32 avpValue)
/* 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 guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, 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 */
@ -1002,7 +1017,7 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
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;
@ -1016,9 +1031,6 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
guint bpos;
static int initialized=FALSE;
/* set our offset */
offset=start;
/*
* Only parse in dictionary if there are diameter packets to
* dissect.
@ -1176,7 +1188,7 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
/* If we have a bad packet, don't bother trying to parse the AVPs */
if (BadPacket) {
return (offset + MAX(pktLength,MIN_DIAMETER_SIZE));
return;
}
/* Start looking at the AVPS */
@ -1195,59 +1207,35 @@ static guint32 dissect_diameter_common(tvbuff_t *tvb, size_t start, packet_info
if (avp_tree != NULL) {
dissect_avps( avp_tvb, pinfo, avp_tree);
}
return MAX((offset + avplength), MIN_DIAMETER_SIZE);
return;
}
return (offset + MAX(pktLength, MIN_DIAMETER_SIZE));
} /* dissect_diameter_common */
static void
dissect_diameter_sctp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static guint
get_diameter_pdu_len(tvbuff_t *tvb, int offset)
{
dissect_diameter_common(tvb, 0, pinfo, tree);
/* Get the length of the Diameter packet. */
return tvb_get_ntoh24(tvb, offset + 1);
}
static void
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)
{
size_t offset = 0;
guint32 plen;
guint32 available_bytes;
/* guint32 noffset; */
/* Loop through the packet, dissecting multiple diameter messages */
do {
available_bytes = tvb_length_remaining(tvb, offset);
if (available_bytes < 4) {
g_warning("Diameter: Bailing because only %d bytes of packet are available",
available_bytes);
return; /* Bail. We can't even get our length */
}
/* get our packet length */
plen = tvb_get_ntohl(tvb, offset);
plen &= 0x00ffffff; /* get rid of the flags */
/*Desegmentation */
if (gbl_diameter_desegment) {
if (pinfo->can_desegment
&& plen > available_bytes) {
pinfo->desegment_offset = offset;
pinfo->desegment_len = plen - available_bytes;
/* g_warning("Diameter: Bailing for deseg because plen(%d) > available(%d)", */
/* plen, available_bytes); */
return;
}
}
/* Otherwise, dissect our packet */
offset = dissect_diameter_common(tvb, offset, pinfo, tree);
/* g_warning("dissected from %d to %d bytes out of %d (available was %d plen was %d)", */
/* offset, noffset, tvb_length(tvb), available_bytes, plen); */
/* offset=noffset; */
} while (offset < tvb_reported_length(tvb));
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 */
/*
@ -1721,17 +1709,17 @@ proto_reg_handoff_diameter(void)
static int TcpPort=0;
static int SctpPort=0;
static dissector_handle_t diameter_tcp_handle;
static dissector_handle_t diameter_sctp_handle;
static dissector_handle_t diameter_handle;
if (!Initialized) {
diameter_tcp_handle = create_dissector_handle(dissect_diameter_tcp,
diameter_tcp_handle = new_create_dissector_handle(dissect_diameter_tcp,
proto_diameter);
diameter_sctp_handle = create_dissector_handle(dissect_diameter_sctp,
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_sctp_handle);
dissector_delete("sctp.port", SctpPort, diameter_handle);
}
/* set port for future deletes */
@ -1741,7 +1729,7 @@ proto_reg_handoff_diameter(void)
/* 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_sctp_handle);
dissector_add("sctp.port", gbl_diameterSctpPort, diameter_handle);
}
/* registration with the filtering engine */