Allow dissectors to be registered as "old-style" or "new-style"
dissectors. "Old-style" dissectors return nothing. "New-style" dissectors return one of: a positive integer, giving the number of bytes worth of data in the tvbuff that it considered to be part of the PDU in the tvbuff; zero, if it didn't consider the data in the tvbuff to be a PDU for its protocol; a negative integer, giving the number of additional bytes worth of data in needs to get the complete PDU (for use with fragmentation/segmentation when the length of the PDU isn't known to the protocol atop the one the dissector is dissecting). Have "call_dissector()" return the return value of new-style dissectors, and the length of the tvbuff handed to it for old-style dissectors. Have "dissector_try_port()" return FALSE if the subdissector is a new-style dissector and returned 0. Make the EAP dissector a new-style dissector, and have a "EAP fragment" dissector that is also a new-style dissector and handles fragmentation of EAP messages (as happens above, for example, RADIUS). Also, clean up some signed vs. unsigned comparison problems. Reassemble EAP-Message AVPs in RADIUS. svn path=/trunk/; revision=4811
This commit is contained in:
parent
fa431b988f
commit
193b8c9bfb
|
@ -1,7 +1,7 @@
|
|||
/* packet.c
|
||||
* Routines for packet disassembly
|
||||
*
|
||||
* $Id: packet.c,v 1.62 2002/02/25 21:02:10 guy Exp $
|
||||
* $Id: packet.c,v 1.63 2002/02/26 11:55:39 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@ethereal.com>
|
||||
|
@ -312,7 +312,11 @@ dissect_packet(epan_dissect_t *edt, union wtap_pseudo_header *pseudo_header,
|
|||
*/
|
||||
struct dissector_handle {
|
||||
const char *name; /* dissector name */
|
||||
dissector_t dissector;
|
||||
gboolean is_new; /* TRUE if new-style dissector */
|
||||
union {
|
||||
dissector_t old;
|
||||
new_dissector_t new;
|
||||
} dissector;
|
||||
int proto_index;
|
||||
};
|
||||
|
||||
|
@ -496,9 +500,11 @@ dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
|
|||
tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
dtbl_entry_t *dtbl_entry;
|
||||
struct dissector_handle *handle;
|
||||
const char *saved_proto;
|
||||
guint32 saved_match_port;
|
||||
guint16 saved_can_desegment;
|
||||
int ret;
|
||||
|
||||
dtbl_entry = g_hash_table_lookup(sub_dissectors->hash_table,
|
||||
GUINT_TO_POINTER(port));
|
||||
|
@ -506,7 +512,8 @@ dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
|
|||
/*
|
||||
* Is there currently a dissector handle for this entry?
|
||||
*/
|
||||
if (dtbl_entry->current == NULL) {
|
||||
handle = dtbl_entry->current;
|
||||
if (handle == NULL) {
|
||||
/*
|
||||
* No - pretend this dissector didn't exist,
|
||||
* so that other dissectors might have a chance
|
||||
|
@ -518,8 +525,8 @@ dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
|
|||
/*
|
||||
* Yes - is its protocol enabled?
|
||||
*/
|
||||
if (dtbl_entry->current->proto_index != -1 &&
|
||||
!proto_is_protocol_enabled(dtbl_entry->current->proto_index)) {
|
||||
if (handle->proto_index != -1 &&
|
||||
!proto_is_protocol_enabled(handle->proto_index)) {
|
||||
/*
|
||||
* No - pretend this dissector didn't exist,
|
||||
* so that other dissectors might have a chance
|
||||
|
@ -545,15 +552,31 @@ dissector_try_port(dissector_table_t sub_dissectors, guint32 port,
|
|||
*/
|
||||
pinfo->can_desegment = saved_can_desegment-(saved_can_desegment>0);
|
||||
pinfo->match_port = port;
|
||||
if (dtbl_entry->current->proto_index != -1) {
|
||||
if (handle->proto_index != -1) {
|
||||
pinfo->current_proto =
|
||||
proto_get_protocol_short_name(dtbl_entry->current->proto_index);
|
||||
proto_get_protocol_short_name(handle->proto_index);
|
||||
}
|
||||
if (handle->is_new)
|
||||
ret = (*handle->dissector.new)(tvb, pinfo, tree);
|
||||
else {
|
||||
(*handle->dissector.old)(tvb, pinfo, tree);
|
||||
ret = 1;
|
||||
}
|
||||
(*dtbl_entry->current->dissector)(tvb, pinfo, tree);
|
||||
pinfo->current_proto = saved_proto;
|
||||
pinfo->match_port = saved_match_port;
|
||||
pinfo->can_desegment = saved_can_desegment;
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* If a new-style dissector returned 0, it means that
|
||||
* it didn't think this tvbuff represented a packet for
|
||||
* its protocol, and didn't dissect anything.
|
||||
*
|
||||
* Old-style dissectors can't reject the packet.
|
||||
*
|
||||
* If the packet was rejected, we return FALSE, otherwise
|
||||
* we return TRUE.
|
||||
*/
|
||||
return ret != 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -983,7 +1006,32 @@ register_dissector(const char *name, dissector_t dissector, int proto)
|
|||
|
||||
handle = g_malloc(sizeof (struct dissector_handle));
|
||||
handle->name = name;
|
||||
handle->dissector = dissector;
|
||||
handle->is_new = FALSE;
|
||||
handle->dissector.old = dissector;
|
||||
handle->proto_index = proto;
|
||||
|
||||
g_hash_table_insert(registered_dissectors, (gpointer)name,
|
||||
(gpointer) handle);
|
||||
}
|
||||
|
||||
void
|
||||
new_register_dissector(const char *name, new_dissector_t dissector, int proto)
|
||||
{
|
||||
struct dissector_handle *handle;
|
||||
|
||||
/* Create our hash table if it doesn't already exist */
|
||||
if (registered_dissectors == NULL) {
|
||||
registered_dissectors = g_hash_table_new(g_str_hash, g_str_equal);
|
||||
g_assert(registered_dissectors != NULL);
|
||||
}
|
||||
|
||||
/* Make sure the registration is unique */
|
||||
g_assert(g_hash_table_lookup(registered_dissectors, name) == NULL);
|
||||
|
||||
handle = g_malloc(sizeof (struct dissector_handle));
|
||||
handle->name = name;
|
||||
handle->is_new = TRUE;
|
||||
handle->dissector.new = dissector;
|
||||
handle->proto_index = proto;
|
||||
|
||||
g_hash_table_insert(registered_dissectors, (gpointer)name,
|
||||
|
@ -991,11 +1039,12 @@ register_dissector(const char *name, dissector_t dissector, int proto)
|
|||
}
|
||||
|
||||
/* Call a dissector through a handle. */
|
||||
void
|
||||
int
|
||||
call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
|
||||
packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
const char *saved_proto;
|
||||
int ret;
|
||||
|
||||
if (handle->proto_index != -1 &&
|
||||
!proto_is_protocol_enabled(handle->proto_index)) {
|
||||
|
@ -1004,8 +1053,8 @@ call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
|
|||
*/
|
||||
g_assert(data_handle != NULL);
|
||||
g_assert(data_handle->proto_index != -1);
|
||||
call_dissector(data_handle,tvb, pinfo, tree);
|
||||
return;
|
||||
call_dissector(data_handle, tvb, pinfo, tree);
|
||||
return tvb_length(tvb);
|
||||
}
|
||||
|
||||
saved_proto = pinfo->current_proto;
|
||||
|
@ -1013,6 +1062,12 @@ call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
|
|||
pinfo->current_proto =
|
||||
proto_get_protocol_short_name(handle->proto_index);
|
||||
}
|
||||
(*handle->dissector)(tvb, pinfo, tree);
|
||||
if (handle->is_new)
|
||||
ret = (*handle->dissector.new)(tvb, pinfo, tree);
|
||||
else {
|
||||
(*handle->dissector.old)(tvb, pinfo, tree);
|
||||
ret = tvb_length(tvb);
|
||||
}
|
||||
pinfo->current_proto = saved_proto;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* packet.h
|
||||
* Definitions for packet disassembly structures and routines
|
||||
*
|
||||
* $Id: packet.h,v 1.53 2002/02/24 06:45:14 guy Exp $
|
||||
* $Id: packet.h,v 1.54 2002/02/26 11:55:39 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@ethereal.com>
|
||||
|
@ -90,9 +90,25 @@ typedef struct dissector_handle *dissector_handle_t;
|
|||
struct dissector_table;
|
||||
typedef struct dissector_table *dissector_table_t;
|
||||
|
||||
/* types for sub-dissector lookup */
|
||||
/*
|
||||
* Dissector that returns nothing.
|
||||
*/
|
||||
typedef void (*dissector_t)(tvbuff_t *, packet_info *, proto_tree *);
|
||||
|
||||
/*
|
||||
* Dissector that returns:
|
||||
*
|
||||
* the amount of data in the protocol's PDU, if it was able to
|
||||
* dissect all the data;
|
||||
*
|
||||
* 0, if the tvbuff doesn't contain a PDU for that protocol;
|
||||
*
|
||||
* the negative of the amount of additional data needed, if
|
||||
* we need more data (e.g., from subsequent TCP segments) to
|
||||
* dissect the entire PDU.
|
||||
*/
|
||||
typedef int (*new_dissector_t)(tvbuff_t *, packet_info *, proto_tree *);
|
||||
|
||||
typedef void (*DATFunc) (gchar *table_name, gpointer key, gpointer value, gpointer user_data);
|
||||
typedef void (*DATFunc_handle) (gchar *table_name, gpointer value, gpointer user_data);
|
||||
|
||||
|
@ -184,6 +200,8 @@ extern gboolean dissector_try_heuristic(heur_dissector_list_t sub_dissectors,
|
|||
/* Register a dissector. */
|
||||
extern void register_dissector(const char *name, dissector_t dissector,
|
||||
int proto);
|
||||
extern void new_register_dissector(const char *name, new_dissector_t dissector,
|
||||
int proto);
|
||||
|
||||
/* Get the short name of the protocol for a dissector handle. */
|
||||
extern char *dissector_handle_get_short_name(dissector_handle_t handle);
|
||||
|
@ -196,7 +214,7 @@ extern dissector_handle_t create_dissector_handle(dissector_t dissector,
|
|||
int proto);
|
||||
|
||||
/* Call a dissector through a handle. */
|
||||
extern void call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
|
||||
extern int call_dissector(dissector_handle_t handle, tvbuff_t *tvb,
|
||||
packet_info *pinfo, proto_tree *tree);
|
||||
|
||||
/* Do all one-time initialization. */
|
||||
|
|
44
packet-eap.c
44
packet-eap.c
|
@ -2,7 +2,7 @@
|
|||
* Routines for EAP Extensible Authentication Protocol dissection
|
||||
* RFC 2284
|
||||
*
|
||||
* $Id: packet-eap.c,v 1.14 2002/02/26 00:51:41 guy Exp $
|
||||
* $Id: packet-eap.c,v 1.15 2002/02/26 11:55:37 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@ethereal.com>
|
||||
|
@ -79,14 +79,15 @@ static const value_string eap_type_vals[] = {
|
|||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
static int
|
||||
dissect_eap_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
|
||||
gboolean fragmented)
|
||||
{
|
||||
guint8 eap_code;
|
||||
guint8 eap_id;
|
||||
guint16 eap_len;
|
||||
guint8 eap_type;
|
||||
guint len;
|
||||
gint len;
|
||||
proto_tree *ti;
|
||||
proto_tree *eap_tree = NULL;
|
||||
|
||||
|
@ -103,9 +104,17 @@ dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
eap_len = tvb_get_ntohs(tvb, 2);
|
||||
len = eap_len;
|
||||
|
||||
/* at least for now, until we get defragmentation support */
|
||||
if (len>tvb_length(tvb))
|
||||
len=tvb_length(tvb);
|
||||
if (fragmented) {
|
||||
/*
|
||||
* This is an EAP fragment inside, for example, RADIUS. If we don't
|
||||
* have all of the packet data, return the negative of the amount of
|
||||
* additional data we need.
|
||||
*/
|
||||
int reported_len = tvb_reported_length_remaining(tvb, 0);
|
||||
|
||||
if (reported_len < len)
|
||||
return -(len - reported_len);
|
||||
}
|
||||
|
||||
if (tree) {
|
||||
ti = proto_tree_add_item(tree, proto_eap, tvb, 0, len, FALSE);
|
||||
|
@ -133,8 +142,8 @@ dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
proto_tree_add_uint(eap_tree, hf_eap_type, tvb, 4, 1, eap_type);
|
||||
|
||||
if (len > 5) {
|
||||
guint offset = 5;
|
||||
guint size = len - offset;
|
||||
int offset = 5;
|
||||
gint size = len - offset;
|
||||
|
||||
switch (eap_type) {
|
||||
|
||||
|
@ -181,6 +190,20 @@ dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tvb_length(tvb);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_eap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
return dissect_eap_data(tvb, pinfo, tree, FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
dissect_eap_fragment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
return dissect_eap_data(tvb, pinfo, tree, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -209,7 +232,8 @@ proto_register_eap(void)
|
|||
proto_register_field_array(proto_eap, hf, array_length(hf));
|
||||
proto_register_subtree_array(ett, array_length(ett));
|
||||
|
||||
register_dissector("eap", dissect_eap, proto_eap);
|
||||
new_register_dissector("eap", dissect_eap, proto_eap);
|
||||
new_register_dissector("eap_fragment", dissect_eap_fragment, proto_eap);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
210
packet-radius.c
210
packet-radius.c
|
@ -2,7 +2,9 @@
|
|||
* Routines for RADIUS packet disassembly
|
||||
* Copyright 1999 Johan Feyaerts
|
||||
*
|
||||
* $Id: packet-radius.c,v 1.48 2002/02/26 00:51:41 guy Exp $
|
||||
* RFC 2865, RFC 2866, RFC 2867, RFC 2868, RFC 2869
|
||||
*
|
||||
* $Id: packet-radius.c,v 1.49 2002/02/26 11:55:37 guy Exp $
|
||||
*
|
||||
* Ethereal - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@ethereal.com>
|
||||
|
@ -53,7 +55,7 @@ static gint ett_radius = -1;
|
|||
static gint ett_radius_avp = -1;
|
||||
static gint ett_radius_eap = -1;
|
||||
|
||||
static dissector_handle_t eap_handle;
|
||||
static dissector_handle_t eap_fragment_handle;
|
||||
|
||||
#define UDP_PORT_RADIUS 1645
|
||||
#define UDP_PORT_RADIUS_NEW 1812
|
||||
|
@ -874,11 +876,15 @@ gchar *rd_value_to_str(e_avphdr *avph, tvbuff_t *tvb, int offset)
|
|||
|
||||
|
||||
void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
|
||||
int avplength,packet_info *pinfo) {
|
||||
int avplength,packet_info *pinfo)
|
||||
{
|
||||
/* adds the attribute value pairs to the tree */
|
||||
e_avphdr avph;
|
||||
gchar *avptpstrval;
|
||||
gchar *valstr;
|
||||
guint8 *reassembled_data = NULL;
|
||||
int reassembled_data_len = 0;
|
||||
int data_needed = 0;
|
||||
|
||||
if (avplength==0)
|
||||
{
|
||||
|
@ -886,59 +892,159 @@ void dissect_attribute_value_pairs(tvbuff_t *tvb, int offset,proto_tree *tree,
|
|||
return;
|
||||
}
|
||||
|
||||
while (avplength > 0 )
|
||||
/*
|
||||
* In case we throw an exception, clean up whatever stuff we've
|
||||
* allocated (if any).
|
||||
*/
|
||||
CLEANUP_PUSH(g_free, reassembled_data);
|
||||
|
||||
while (avplength > 0)
|
||||
{
|
||||
tvb_memcpy(tvb,(guint8 *)&avph,offset,sizeof(e_avphdr));
|
||||
avptpstrval = match_strval(avph.avp_type, radius_attrib_type_vals);
|
||||
if (avptpstrval == NULL)
|
||||
avptpstrval = "Unknown Type";
|
||||
if (avph.avp_length < 2) {
|
||||
/*
|
||||
* This AVP is bogus - the length includes the type and length
|
||||
* fields, so it must be >= 2.
|
||||
*/
|
||||
proto_tree_add_text(tree, tvb, offset, avph.avp_length,
|
||||
"t:%s(%u) l:%u (length not >= 2)",
|
||||
avptpstrval,avph.avp_type,avph.avp_length);
|
||||
break;
|
||||
}
|
||||
|
||||
tvb_memcpy(tvb,(guint8 *)&avph,offset,sizeof(e_avphdr));
|
||||
avptpstrval=match_strval(avph.avp_type, radius_attrib_type_vals);
|
||||
if (avptpstrval == NULL) avptpstrval="Unknown Type";
|
||||
if (avph.avp_length < 2) {
|
||||
/*
|
||||
* This AVP is bogus - the length includes the type and length
|
||||
* fields, so it must be >= 2.
|
||||
*/
|
||||
proto_tree_add_text(tree, tvb, offset, avph.avp_length,
|
||||
"t:%s(%u) l:%u (length not >= 2)",
|
||||
avptpstrval,avph.avp_type,avph.avp_length);
|
||||
break;
|
||||
}
|
||||
if (avph.avp_type == RD_TP_EAP_MESSAGE) {
|
||||
proto_item *ti;
|
||||
proto_tree *eap_tree;
|
||||
gint tvb_len;
|
||||
tvbuff_t *next_tvb;
|
||||
int data_len;
|
||||
int result;
|
||||
|
||||
if (avph.avp_type == RD_TP_EAP_MESSAGE) {
|
||||
proto_item *ti;
|
||||
proto_tree *eap_tree;
|
||||
gint tvb_len;
|
||||
tvbuff_t *next_tvb;
|
||||
ti = proto_tree_add_text(tree, tvb,offset,avph.avp_length,"t:%s(%u) l:%u",
|
||||
avptpstrval,avph.avp_type,avph.avp_length);
|
||||
eap_tree = proto_item_add_subtree(ti, ett_radius_eap);
|
||||
tvb_len = tvb_length_remaining(tvb, offset+2);
|
||||
if (avph.avp_length-2 < tvb_len)
|
||||
tvb_len = avph.avp_length-2;
|
||||
next_tvb = tvb_new_subset(tvb, offset+2, tvb_len, avph.avp_length-2);
|
||||
ti = proto_tree_add_text(tree, tvb,offset,avph.avp_length,"t:%s(%u) l:%u",
|
||||
avptpstrval,avph.avp_type,avph.avp_length);
|
||||
eap_tree = proto_item_add_subtree(ti, ett_radius_eap);
|
||||
tvb_len = tvb_length_remaining(tvb, offset+2);
|
||||
data_len = avph.avp_length-2;
|
||||
if (data_len < tvb_len)
|
||||
tvb_len = data_len;
|
||||
next_tvb = tvb_new_subset(tvb, offset+2, tvb_len, data_len);
|
||||
|
||||
/*
|
||||
* Set the columns non-writable, so that the packet list
|
||||
* shows this as an RADIUS packet, not as an EAP packet.
|
||||
*
|
||||
* XXX - we'll call the EAP dissector only if we're building
|
||||
* a protocol tree. The EAP dissector currently saves no state,
|
||||
* and won't be modifying the columns, so that's OK right now,
|
||||
* but it might call the SSL dissector - if that maintains state
|
||||
* needed for dissection, we'll have to arrange that AVPs be
|
||||
* dissected even if we're not building a protocol tree.
|
||||
*/
|
||||
col_set_writable(pinfo->cinfo, FALSE);
|
||||
call_dissector(eap_handle, next_tvb, pinfo, eap_tree);
|
||||
} else {
|
||||
valstr=rd_value_to_str(&avph, tvb, offset);
|
||||
proto_tree_add_text(tree, tvb,offset,avph.avp_length,
|
||||
"t:%s(%u) l:%u, %s",
|
||||
avptpstrval,avph.avp_type,avph.avp_length,valstr);
|
||||
}
|
||||
/*
|
||||
* Set the columns non-writable, so that the packet list
|
||||
* shows this as an RADIUS packet, not as an EAP packet.
|
||||
*
|
||||
* XXX - we'll call the EAP dissector only if we're building
|
||||
* a protocol tree. The EAP dissector currently saves no state,
|
||||
* and won't be modifying the columns, so that's OK right now,
|
||||
* but it might call the SSL dissector - if that maintains state
|
||||
* needed for dissection, we'll have to arrange that AVPs be
|
||||
* dissected even if we're not building a protocol tree.
|
||||
*/
|
||||
col_set_writable(pinfo->cinfo, FALSE);
|
||||
|
||||
offset=offset+avph.avp_length;
|
||||
avplength=avplength-avph.avp_length;
|
||||
/*
|
||||
* RFC 2869 says, in section 5.13, describing the EAP-Message
|
||||
* attribute:
|
||||
*
|
||||
* The String field contains EAP packets, as defined in [3]. If
|
||||
* multiple EAP-Message attributes are present in a packet their
|
||||
* values should be concatenated; this allows EAP packets longer than
|
||||
* 253 octets to be passed by RADIUS.
|
||||
*
|
||||
* Do reassembly of EAP-Message attributes.
|
||||
*/
|
||||
|
||||
/* Are we in the process of reassembling? */
|
||||
if (reassembled_data != NULL) {
|
||||
/* Yes - show this as an EAP fragment. */
|
||||
proto_tree_add_text(eap_tree, next_tvb, 0, -1, "EAP fragment");
|
||||
|
||||
/*
|
||||
* Do we have all of the data in this fragment?
|
||||
*/
|
||||
if (tvb_len >= data_len) {
|
||||
/*
|
||||
* Yes - add it to the reassembled data.
|
||||
*/
|
||||
tvb_memcpy(next_tvb, reassembled_data + reassembled_data_len,
|
||||
0, data_len);
|
||||
reassembled_data_len += data_len;
|
||||
data_needed -= data_len;
|
||||
if (data_needed <= 0) {
|
||||
/*
|
||||
* We got at least as much data as we needed; we're done
|
||||
* reassembling.
|
||||
* XXX - what if we got more?
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocate a new tvbuff, referring to the reassembled payload.
|
||||
*/
|
||||
next_tvb = tvb_new_real_data(reassembled_data, reassembled_data_len,
|
||||
reassembled_data_len);
|
||||
|
||||
/*
|
||||
* We have a tvbuff that refers to this data, so we shouldn't
|
||||
* free this data if we throw an exception; clear
|
||||
* "reassembled_data", so the cleanup handler won't free it.
|
||||
*/
|
||||
reassembled_data = NULL;
|
||||
reassembled_data_len = 0;
|
||||
data_needed = 0;
|
||||
|
||||
/*
|
||||
* Arrange that the allocated packet data copy be freed when the
|
||||
* tvbuff is freed.
|
||||
*/
|
||||
tvb_set_free_cb(next_tvb, g_free);
|
||||
|
||||
/*
|
||||
* Add the tvbuff to the list of tvbuffs to which the tvbuff we
|
||||
* were handed refers, so it'll get cleaned up when that tvbuff
|
||||
* is cleaned up.
|
||||
*/
|
||||
tvb_set_child_real_data_tvbuff(tvb, next_tvb);
|
||||
|
||||
/* Add the defragmented data to the data source list. */
|
||||
add_new_data_source(pinfo->fd, next_tvb, "Reassembled EAP");
|
||||
|
||||
/* Now dissect it. */
|
||||
call_dissector(eap_fragment_handle, next_tvb, pinfo, eap_tree);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* No - hand it to the dissector.
|
||||
*/
|
||||
result = call_dissector(eap_fragment_handle, next_tvb, pinfo, eap_tree);
|
||||
if (result < 0) {
|
||||
/* This is only part of the full EAP packet; start reassembly. */
|
||||
proto_tree_add_text(eap_tree, next_tvb, 0, -1, "EAP fragment");
|
||||
reassembled_data_len = data_len;
|
||||
data_needed = -result;
|
||||
reassembled_data = g_malloc(reassembled_data_len + data_needed);
|
||||
tvb_memcpy(next_tvb, reassembled_data, 0, reassembled_data_len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
valstr = rd_value_to_str(&avph, tvb, offset);
|
||||
proto_tree_add_text(tree, tvb,offset,avph.avp_length,
|
||||
"t:%s(%u) l:%u, %s",
|
||||
avptpstrval,avph.avp_type,avph.avp_length,valstr);
|
||||
}
|
||||
|
||||
offset = offset+avph.avp_length;
|
||||
avplength = avplength-avph.avp_length;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the cleanup handler to free any reassembled data we haven't
|
||||
* attached to a tvbuff, and pop the handler.
|
||||
*/
|
||||
CLEANUP_CALL_AND_POP;
|
||||
}
|
||||
|
||||
static void dissect_radius(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
|
@ -1046,9 +1152,9 @@ proto_reg_handoff_radius(void)
|
|||
dissector_handle_t radius_handle;
|
||||
|
||||
/*
|
||||
* Get a handle for the EAP dissector.
|
||||
* Get a handle for the EAP fragment dissector.
|
||||
*/
|
||||
eap_handle = find_dissector("eap");
|
||||
eap_fragment_handle = find_dissector("eap_fragment");
|
||||
|
||||
radius_handle = create_dissector_handle(dissect_radius, proto_radius);
|
||||
dissector_add("udp.port", UDP_PORT_RADIUS, radius_handle);
|
||||
|
|
Loading…
Reference in New Issue