Ethereal-dev: [Ethereal-dev] Patch for wiretap and conversations support for RSVP

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Manu Pathak <mapathak@xxxxxxxxx>
Date: Sun, 21 Aug 2005 02:55:17 -0400
Hi,

   Attached is a patch which adds support for wiretap and conversations
to RSVP. I have done some testing and verified that it is working as
expected. As this is the first time I have implemented these features for a
protocol, would somebody who has done this before care to take a look at
the diffs and provide some feedback? Can this be checked into the mainline
code? I would be happy to answer any questions related to these changes
if any come up. Thanks,

Manu

--
----------------------------------------------------------------------
You know the world is going crazy when the best rapper is a white guy,
the best golfer is a black guy, the tallest guy in the NBA is Chinese,
the Swiss hold the America's Cup, France is accusing the U.S. of
arrogance, Germany doesn't want to go to war, and the three most
powerful men in America are named 'Bush', 'Dick', and 'Colon.' Need I
say more?
                                                          -Chris Rock
Index: gtk/hostlist_rsvp.c
===================================================================
--- gtk/hostlist_rsvp.c	(revision 0)
+++ gtk/hostlist_rsvp.c	(revision 0)
@@ -0,0 +1,95 @@
+/* hostlist_rsvp.c
+ * hostlist_rsvp.c August 2005, Manu Pathak <mapathak@xxxxxxxxx>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include "epan/packet.h"
+#include "stat_menu.h"
+#include <epan/tap.h>
+#include "../register.h"
+#include "hostlist_table.h"
+#include <epan/dissectors/packet-rsvp.h>
+
+
+static int
+rsvp_hostlist_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
+{
+	hostlist_table *hosts=(hostlist_table *)pit;
+	const rsvp_conversation_info *rsvph = vip;
+
+	/* Take two "add" passes per packet, adding for each direction, ensures
+	 * that all packets are counted properly (even if address is sending to 
+	 * itself). XXX - this could probably be done more efficiently inside 
+	 * hostlist_table 
+	 */
+	add_hostlist_table_data(hosts, &rsvph->source, 0, TRUE, 1, 
+				pinfo->fd->pkt_len, SAT_NONE, PT_NONE);
+	add_hostlist_table_data(hosts, &rsvph->destination, 0, FALSE, 1, 
+				pinfo->fd->pkt_len, SAT_NONE, PT_NONE);
+	return 1;
+}
+
+static void
+gtk_rsvp_hostlist_init(char *optarg)
+{
+	char *filter=NULL;
+
+	if(!strncmp(optarg,"hosts,rsvp,",11)){
+		filter=optarg+11;
+	} else {
+		filter=NULL;
+	}
+
+	init_hostlist_table(TRUE, "RSVP Hosts", "rsvp", filter, 
+			    rsvp_hostlist_packet);
+
+}
+
+
+static void
+gtk_rsvp_hostlist_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+	gtk_rsvp_hostlist_init("hosts,rsvp");
+}
+
+
+void
+register_tap_listener_rsvp_hostlist(void)
+{
+	register_stat_cmd_arg("hosts,rsvp", gtk_rsvp_hostlist_init);
+
+	register_stat_menu_item("RSVP", REGISTER_STAT_GROUP_ENDPOINT_LIST,
+			       gtk_rsvp_hostlist_cb, NULL, NULL, NULL);
+
+	register_hostlist_table(TRUE, "RSVP", "rsvp", NULL /*filter*/, 
+				rsvp_hostlist_packet);
+}
Index: gtk/conversations_rsvp.c
===================================================================
--- gtk/conversations_rsvp.c	(revision 0)
+++ gtk/conversations_rsvp.c	(revision 0)
@@ -0,0 +1,88 @@
+/* conversations_rsvp.c
+ * conversations_rsvp.c  August 2005, Manu Pathak <mapathak@xxxxxxxxx>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@xxxxxxxxxxxx>
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <string.h>
+#include "epan/packet.h"
+#include <epan/stat_cmd_args.h>
+#include "stat_menu.h"
+#include <epan/tap.h>
+#include "../register.h"
+#include "conversations_table.h"
+#include <epan/dissectors/packet-rsvp.h>
+
+
+static int
+rsvp_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip)
+{
+	const rsvp_conversation_info *rsvph = vip;
+
+	add_conversation_table_data((conversations_table *)pct, 
+				    &rsvph->source, &rsvph->destination, 0, 0, 1, 
+				    pinfo->fd->pkt_len, SAT_NONE, PT_NONE);
+
+	return 1;
+}
+
+static void
+rsvp_conversation_init(char *optarg)
+{
+	char *filter=NULL;
+
+	if(!strncmp(optarg,"conv,rsvp,",10)){
+		filter=optarg+10;
+	} else {
+		filter=NULL;
+	}
+
+	init_conversation_table(TRUE, "RSVP", "rsvp", filter, 
+				rsvp_conversation_packet);
+
+}
+
+
+static void
+rsvp_endpoints_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+	rsvp_conversation_init("conv,rsvp");
+}
+
+
+void
+register_tap_listener_rsvp_conversation(void)
+{
+	register_stat_cmd_arg("conv,rsvp", rsvp_conversation_init);
+
+	register_stat_menu_item("RSVP", REGISTER_STAT_GROUP_CONVERSATION_LIST,
+			       rsvp_endpoints_cb, NULL, NULL, NULL);
+
+	register_conversation_table(TRUE, "RSVP", "rsvp", NULL /*filter*/, 
+				    rsvp_conversation_packet);
+}
Index: gtk/Makefile.common
===================================================================
--- gtk/Makefile.common	(revision 15492)
+++ gtk/Makefile.common	(working copy)
@@ -120,6 +120,7 @@
 	conversations_tr.c	\
 	conversations_udpip.c	\
 	conversations_wlan.c	\
+	conversations_rsvp.c	\
 	dcerpc_stat.c	\
 	fc_stat.c	\
 	flow_graph.c	\
@@ -138,6 +139,7 @@
 	hostlist_tr.c \
 	hostlist_udpip.c \
 	hostlist_wlan.c \
+	hostlist_rsvp.c \
 	io_stat.c	\
 	ldap_stat.c	\
 	mgcp_stat.c	\
Index: epan/dissectors/packet-rsvp.c
===================================================================
--- epan/dissectors/packet-rsvp.c	(revision 15492)
+++ epan/dissectors/packet-rsvp.c	(working copy)
@@ -76,6 +76,8 @@
 #include <epan/in_cksum.h>
 #include "etypes.h"
 #include <epan/ipproto.h>
+#include <epan/conversation.h>
+#include <epan/tap.h>
 
 #include "packet-rsvp.h"
 #include "packet-ip.h"
@@ -84,7 +86,109 @@
 
 static int proto_rsvp = -1;
 
+static dissector_table_t rsvp_dissector_table;
+static dissector_handle_t data_handle;
+
+static int rsvp_tap = -1;
+
+/* 
+ * Support for RSVP conversations
+ */
+static int rsvp_packet_init_count = 100; 
+
+static rsvp_conversation_info rsvphstruct[4];
+static rsvp_conversation_info *rsvph;
+static int rsvph_count = 0;
+
 /*
+ * All RSVP packets belonging to a particular flow  belong to the same 
+ * conversation. The following structure definitions are for auxillary
+ * structures which have all the relevant flow information to make up the
+ * RSVP five-tuple. Note that the values of the five-tuple are determined
+ * from the session object and sender template/filter spec for PATH/RESV
+ * messages.
+ * Update rsvp_request_equal() when you add stuff here. You might also
+ * have to update rsvp_request_hash().
+ * TODO: Support for IPv6 conversations.
+ */
+
+typedef struct rsvp_session_ipv4_info {
+    address destination;
+    guint8 protocol;
+    guint16 udp_dest_port;
+} rsvp_session_ipv4_info;
+
+typedef struct rsvp_session_ipv6_info {
+    /* not supported yet */
+
+} rsvp_session_ipv6_info;
+
+typedef struct rsvp_session_ipv4_lsp_info {
+    address destination;
+    guint16 udp_dest_port;
+    guint32 ext_tunnel_id;
+} rsvp_session_ipv4_lsp_info;
+
+typedef struct rsvp_session_ipv4_uni_info {
+    address destination;
+    guint16 udp_dest_port;
+    guint32 ext_tunnel_id;
+} rsvp_session_ipv4_uni_info;
+
+typedef struct rsvp_session_ipv4_enni_info {
+    address destination;
+    guint16 udp_dest_port;
+    guint32 ext_tunnel_id;
+} rsvp_session_ipv4_enni_info;
+
+typedef struct rsvp_template_filter_info {
+    address source;
+    guint16 udp_source_port;
+} rsvp_template_filter_info;
+
+/* 
+ * The actual request key consists of a union of the various session objects
+ * (which are uniquely identified based on the session type), and the 
+ * source_info structure, which has the information derived from the sender 
+ * template or the filter spec.
+ * The request key is populated by copying the information from the 
+ * rsvp_conversation_info structure (rsvph), which in turn is populated when
+ * the session, filter and sender template objects are dissected.
+ */
+struct rsvp_request_key {
+    guint32 session_type;
+
+    union { /* differentiated by session_type field */
+	rsvp_session_ipv4_info session_ipv4;
+	rsvp_session_ipv6_info session_ipv6;
+	rsvp_session_ipv4_lsp_info session_ipv4_lsp;
+	rsvp_session_ipv4_uni_info session_ipv4_uni;
+	rsvp_session_ipv4_enni_info session_ipv4_enni;
+    } u;
+
+    rsvp_template_filter_info source_info;
+    guint32 conversation;
+};
+
+/*
+ * At present, there is nothing particularly important that we need to
+ * store for the request value for each rsvp_request_key, so we just
+ * store the unique 32-bit identifier internally allocated for the key
+ * (and stored in the conversation attribute of rsvp_request_key above.
+ * If this changes in the future, then other stuff can be added here.
+ */
+struct rsvp_request_val {
+    guint32 value;
+};
+
+/*
+ * Initialize the conversation related data structures.
+ */
+static GHashTable *rsvp_request_hash = NULL;
+static GMemChunk  *rsvp_request_keys = NULL;
+static GMemChunk  *rsvp_request_vals = NULL;
+
+/*
  * The list of tree types
  */
 enum {
@@ -1065,6 +1169,155 @@
 
 };
 
+/* RSVP Conversation related Hash functions */
+
+/*
+ * Compare two RSVP request keys to see if they are equal. Return 1 if they
+ * are, 0 otherwise.
+ * Two RSVP request keys are equal if and only if they have the exactly the
+ * same internal conversation identifier, session type, and matching values in 
+ * the session info and source info structures.
+ */
+static gint 
+rsvp_equal (gconstpointer k1, gconstpointer k2)
+{
+    const struct rsvp_request_key *key1 = (const struct rsvp_request_key*) k1;
+    const struct rsvp_request_key *key2 = (const struct rsvp_request_key*) k2;
+
+    if (key1->conversation != key2->conversation) {
+	return 0;
+    }
+
+    if (key1->session_type != key2->session_type) {
+	return 0;
+    }
+
+    switch (key1->session_type) {
+    case RSVP_SESSION_TYPE_IPV4:
+	if (ADDRESSES_EQUAL(&key1->u.session_ipv4.destination,
+			    &key2->u.session_ipv4.destination) == FALSE)
+	    return 0;
+
+	if (key1->u.session_ipv4.protocol != key2->u.session_ipv4.protocol)
+	    return 0;
+	
+	if (key1->u.session_ipv4.udp_dest_port != key2->u.session_ipv4.udp_dest_port)
+	    return 0;
+	
+	break;
+
+    case RSVP_SESSION_TYPE_IPV6:
+	/* this is not supported yet for conversations */
+	return 1;
+	break;
+
+    case RSVP_SESSION_TYPE_IPV4_LSP:
+	if (ADDRESSES_EQUAL(&key1->u.session_ipv4_lsp.destination,
+			    &key2->u.session_ipv4_lsp.destination) == FALSE)
+	    return 0;
+	
+	if (key1->u.session_ipv4_lsp.udp_dest_port != 
+	    key2->u.session_ipv4_lsp.udp_dest_port)
+	    return 0;
+
+	
+	if (key1->u.session_ipv4_lsp.ext_tunnel_id != 
+	    key2->u.session_ipv4_lsp.ext_tunnel_id)
+	    return 0;
+
+	break;
+
+    case RSVP_SESSION_TYPE_IPV4_UNI:
+	if (ADDRESSES_EQUAL(&key1->u.session_ipv4_uni.destination,
+			    &key2->u.session_ipv4_uni.destination) == FALSE)
+	    return 0;
+	
+	if (key1->u.session_ipv4_uni.udp_dest_port != 
+	    key2->u.session_ipv4_uni.udp_dest_port)
+	    return 0;
+
+	
+	if (key1->u.session_ipv4_uni.ext_tunnel_id != 
+	    key2->u.session_ipv4_uni.ext_tunnel_id)
+	    return 0;
+
+	break;
+
+    case RSVP_SESSION_TYPE_IPV4_E_NNI:
+	if (ADDRESSES_EQUAL(&key1->u.session_ipv4_enni.destination,
+			    &key2->u.session_ipv4_enni.destination) == FALSE)
+	    return 0;
+	
+	if (key1->u.session_ipv4_enni.udp_dest_port != 
+	    key2->u.session_ipv4_enni.udp_dest_port)
+	    return 0;
+
+	
+	if (key1->u.session_ipv4_enni.ext_tunnel_id != 
+	    key2->u.session_ipv4_enni.ext_tunnel_id)
+	    return 0;
+
+	break;
+
+    default:
+	/* This should never happen. */
+	break;
+    }
+
+    if (ADDRESSES_EQUAL(&key1->source_info.source, 
+			&key2->source_info.source) == FALSE)
+	return 0;
+
+    if (key1->source_info.udp_source_port != key2->source_info.udp_source_port)
+	return 0;
+
+    /* If we get here, the two keys are equal. */
+    return 1;
+}
+
+/*
+ * Calculate a hash key for the supplied RSVP request. The internally allocated 
+ * conversation-id is unique, so we just use that.
+ */
+static guint 
+rsvp_hash (gconstpointer k)
+{
+    const struct rsvp_request_key *key = (const struct rsvp_request_key*) k;
+    return key->conversation;
+}
+
+/*
+ * Conversation specific initialization code that deletes any unused memory that 
+ * might need to be freed, and allocates the memory for the various conversation
+ * hash tables.
+ */
+static void
+rsvp_init_protocol (void)
+{
+    if (rsvp_request_hash)
+	g_hash_table_destroy(rsvp_request_hash);
+
+    if (rsvp_request_keys)
+	g_mem_chunk_destroy(rsvp_request_keys);
+
+    if (rsvp_request_vals)
+	g_mem_chunk_destroy(rsvp_request_vals);
+
+    rsvp_request_hash = g_hash_table_new(rsvp_hash, rsvp_equal);
+
+    rsvp_request_keys = 
+	g_mem_chunk_new("rsvp_request_keys",
+			sizeof(struct rsvp_request_key),
+			rsvp_packet_init_count * sizeof(struct rsvp_request_key),
+			G_ALLOC_AND_FREE);
+
+    rsvp_request_vals = 
+	g_mem_chunk_new("rsvp_request_vals",
+			sizeof(struct rsvp_request_val),
+			rsvp_packet_init_count * sizeof(struct rsvp_request_val),
+			G_ALLOC_AND_FREE);
+}
+
 static inline int rsvp_class_to_filter_num(int classnum)
 {
     switch(classnum) {
@@ -1341,6 +1594,17 @@
 	proto_tree_add_item(rsvp_object_tree,
 			    rsvp_filter[RSVPF_SESSION_PORT], tvb,
 			    offset2+6, 2, FALSE);
+
+	/*
+	 * Save this information to build the conversation request key
+	 * later.
+	 */
+	rsvph->session_type = RSVP_SESSION_TYPE_IPV4;
+	SET_ADDRESS(&rsvph->destination, AT_IPv4, 4,
+                    tvb_get_ptr(tvb, offset2, 4));
+	rsvph->protocol = tvb_get_guint8(tvb, offset2+4);
+	rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
+
 	break;
 
     case RSVP_SESSION_TYPE_IPV6:
@@ -1358,6 +1622,13 @@
 	proto_tree_add_text(rsvp_object_tree, tvb, offset2+18, 2,
 			    "Destination port: %u",
 			    tvb_get_ntohs(tvb, offset2+18));
+	/*
+	 * Save this information to build the conversation request key 
+	 * later. IPv6 conversatiuon support is not implemented yet, so only 
+	 * the session type is stored.
+	 */
+	rsvph->session_type = RSVP_SESSION_TYPE_IPV6;
+
 	break;
 
     case RSVP_SESSION_TYPE_IPV4_LSP:
@@ -1378,6 +1649,16 @@
 	proto_tree_add_item_hidden(rsvp_object_tree,
 				   rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
 				   tvb, offset2+8, 4, FALSE);
+
+	/* 
+	 * Save this information to build the conversation request key 
+	 * later.
+	 */
+	rsvph->session_type = RSVP_SESSION_TYPE_IPV4_LSP;
+	SET_ADDRESS(&rsvph->destination, AT_IPv4, 4, 
+		    tvb_get_ptr(tvb, offset2, 4));
+	rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
+	rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
 	break;
 
     case RSVP_SESSION_TYPE_IPV4_UNI:
@@ -1397,6 +1678,17 @@
 	proto_tree_add_item_hidden(rsvp_object_tree,
 				   rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
 				   tvb, offset2+8, 4, FALSE);
+
+	/* 
+	 * Save this information to build the conversation request key 
+	 * later.
+	 */
+	rsvph->session_type = RSVP_SESSION_TYPE_IPV4_UNI;
+	SET_ADDRESS(&rsvph->destination, AT_IPv4, 4, 
+		    tvb_get_ptr(tvb, offset2, 4));
+	rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
+	rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
+
 	break;
 
     case RSVP_SESSION_TYPE_IPV4_E_NNI:
@@ -1416,6 +1708,17 @@
 	proto_tree_add_item_hidden(rsvp_object_tree,
 				   rsvp_filter[RSVPF_SESSION_EXT_TUNNEL_ID],
 				   tvb, offset2+8, 4, FALSE);
+
+	/* 
+	 * Save this information to build the conversation request key 
+	 * later.
+	 */
+	rsvph->session_type = RSVP_SESSION_TYPE_IPV4_E_NNI;
+	SET_ADDRESS(&rsvph->destination, AT_IPv4, 4, 
+		    tvb_get_ptr(tvb, offset2, 4));
+	rsvph->udp_dest_port = tvb_get_ntohs(tvb, offset2+6);
+	rsvph->ext_tunnel_id = tvb_get_ntohl(tvb, offset2 + 8);
+
 	break;
 
     default:
@@ -1905,6 +2208,12 @@
 	 proto_tree_add_item(rsvp_object_tree,
 			     rsvp_filter[RSVPF_SENDER_PORT],
 			     tvb, offset2+6, 2, FALSE);
+
+	 /*
+	  * Save this information to build the conversation request key later.
+	  */
+	 SET_ADDRESS(&rsvph->source, AT_IPv4, 4, tvb_get_ptr(tvb, offset2, 4));
+	 rsvph->udp_source_port = tvb_get_ntohs(tvb, offset2+6);
 	 break;
 
      case 2:
@@ -1927,6 +2236,12 @@
 	 proto_tree_add_item(rsvp_object_tree,
 			     rsvp_filter[RSVPF_SENDER_LSP_ID],
 			     tvb, offset2+6, 2, FALSE);
+
+	 /*
+	  * Save this information to build the conversation request key later.
+	  */
+	 SET_ADDRESS(&rsvph->source, AT_IPv4, 4, tvb_get_ptr(tvb, offset2, 4));
+	 rsvph->udp_source_port = tvb_get_ntohs(tvb, offset2+6);
 	 break;
 
      default:
@@ -4761,6 +5076,10 @@
     int msg_length;
     int session_off, tempfilt_off;
 
+    conversation_t *conversation;
+    struct rsvp_request_key request_key, *new_request_key;
+    struct rsvp_request_val *request_val = NULL;
+
     if (check_col(pinfo->cinfo, COL_PROTOCOL))
         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RSVP");
     if (check_col(pinfo->cinfo, COL_INFO))
@@ -4770,6 +5089,16 @@
     message_type = tvb_get_guint8(tvb, 1);
     msg_length = tvb_get_ntohs(tvb, 6);
 
+    rsvph_count++;
+    if (rsvph_count>=4) {
+	rsvph_count = 0;
+    }
+    rsvph = &rsvphstruct[rsvph_count];
+
+    /* Copy over the source and destination addresses from the pinfo strucutre */
+    SET_ADDRESS(&rsvph->source, pinfo->src.type, pinfo->src.len, pinfo->src.data);
+    SET_ADDRESS(&rsvph->destination, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
+
     if (check_col(pinfo->cinfo, COL_INFO)) {
         col_add_str(pinfo->cinfo, COL_INFO,
             val_to_str(message_type, message_type_vals, "Unknown (%u). "));
@@ -4800,6 +5129,85 @@
     if (tree) {
 	dissect_rsvp_msg_tree(tvb, pinfo, tree, TREE(TT_RSVP));
     }
+
+    /* Find out what conversation this packet is part of. */
+    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, 
+				     pinfo->ptype, pinfo->srcport, 
+				     pinfo->destport, 0);
+
+    if (conversation == NULL) {
+	/* Not part of any conversation; create a new one. */
+	conversation = 
+	    conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
+			     pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+    }
+
+    /* Now build the request key */
+    request_key.conversation = conversation->index;
+    request_key.session_type = rsvph->session_type;
+
+    switch (request_key.session_type) {
+    case RSVP_SESSION_TYPE_IPV4:
+	SET_ADDRESS(&request_key.u.session_ipv4.destination, 
+		    rsvph->destination.type, rsvph->destination.len,
+		    rsvph->destination.data);
+	request_key.u.session_ipv4.protocol = rsvph->protocol;
+	request_key.u.session_ipv4.udp_dest_port = rsvph->udp_dest_port;
+	break;
+
+    case RSVP_SESSION_TYPE_IPV6:
+	/* Not supported yet */
+	break;
+
+    case RSVP_SESSION_TYPE_IPV4_LSP:
+	SET_ADDRESS(&request_key.u.session_ipv4_lsp.destination, 
+		    rsvph->destination.type, rsvph->destination.len,
+		    rsvph->destination.data);
+	request_key.u.session_ipv4_lsp.udp_dest_port = rsvph->udp_dest_port;
+	request_key.u.session_ipv4_lsp.ext_tunnel_id = rsvph->ext_tunnel_id;
+	break;
+
+    case RSVP_SESSION_TYPE_IPV4_UNI:
+	SET_ADDRESS(&request_key.u.session_ipv4_uni.destination, 
+		    rsvph->destination.type, rsvph->destination.len,
+		    rsvph->destination.data);
+	request_key.u.session_ipv4_uni.udp_dest_port = rsvph->udp_dest_port;
+	request_key.u.session_ipv4_uni.ext_tunnel_id = rsvph->ext_tunnel_id;
+	break;
+
+    case RSVP_SESSION_TYPE_IPV4_E_NNI:
+	SET_ADDRESS(&request_key.u.session_ipv4_enni.destination, 
+		    rsvph->destination.type, rsvph->destination.len,
+		    rsvph->destination.data);
+	request_key.u.session_ipv4_enni.udp_dest_port = rsvph->udp_dest_port;
+	request_key.u.session_ipv4_enni.ext_tunnel_id = rsvph->ext_tunnel_id;
+	break;
+    default:
+	/* This should never happen. */
+	break;
+    }
+
+    SET_ADDRESS(&request_key.source_info.source, 
+		rsvph->source.type, rsvph->source.len, rsvph->source.data);
+    request_key.source_info.udp_source_port = rsvph->udp_source_port;
+
+    /* See if a request with this key already exists */
+    request_val = 
+	(struct rsvp_request_val *) g_hash_table_lookup(rsvp_request_hash,
+							&request_key);
+
+    /* If not, insert the new request key into the hash table */
+    if (!request_val) {
+	new_request_key = g_mem_chunk_alloc(rsvp_request_keys);
+	*new_request_key = request_key;
+
+	request_val = g_mem_chunk_alloc(rsvp_request_vals);
+	request_val->value = conversation->index;
+
+	g_hash_table_insert(rsvp_request_hash, new_request_key, request_val);
+    }
+
+    tap_queue_packet(rsvp_tap, pinfo, rsvph);
 }
 
 static void
@@ -4829,6 +5237,12 @@
     proto_register_field_array(proto_rsvp, rsvpf_info, array_length(rsvpf_info));
     proto_register_subtree_array(ett_tree, array_length(ett_tree));
     register_rsvp_prefs();
+
+    rsvp_dissector_table = register_dissector_table("rsvp.proto", "RSVP Protocol",
+						    FT_UINT8, BASE_DEC);
+						    
+    /* Initialization routine for RSVP conversations */
+    register_init_routine(&rsvp_init_protocol);
 }
 
 void
@@ -4838,4 +5252,6 @@
 
 	rsvp_handle = create_dissector_handle(dissect_rsvp, proto_rsvp);
 	dissector_add("ip.proto", IP_PROTO_RSVP, rsvp_handle);
+	data_handle = find_dissector("data");
+	rsvp_tap = register_tap("rsvp");
 }
Index: epan/dissectors/packet-rsvp.h
===================================================================
--- epan/dissectors/packet-rsvp.h	(revision 15492)
+++ epan/dissectors/packet-rsvp.h	(working copy)
@@ -25,6 +25,18 @@
 #ifndef PACKET_RSVP_H
 #define PACKET_RSVP_H
 
+/* RSVP conversations support */
+typedef struct rsvp_conversation_info
+{
+    guint8 session_type;
+    address source;
+    address destination;
+    guint16 udp_source_port;
+    guint16 udp_dest_port;
+    guint8  protocol;
+    guint32 ext_tunnel_id; 
+} rsvp_conversation_info;
+
 extern const value_string gmpls_switching_type_str[];
 extern const value_string gmpls_lsp_enc_str[];
 extern const value_string gmpls_protection_cap_str[];