Tvbuffify the portmap/rpcbind dissector, and implement part of CALLIT
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 6 Feb 2001 06:46:10 +0000 (06:46 +0000)
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>
Tue, 6 Feb 2001 06:46:10 +0000 (06:46 +0000)
dissection (dissection of V2 CALLIT calls; no V3/V4 stuff or reply
handling yet).

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@2994 f5534014-38df-0310-8fa8-9805f1628bb7

packet-portmap.c
packet-rpc.c
packet-rpc.h

index f0add47dd1b91d82c0f32b5098488daace185acd..372da8688ff47e78d47d470630ab9df2ae8e0ae0 100644 (file)
@@ -1,7 +1,7 @@
 /* packet-portmap.c
  * Routines for portmap dissection
  *
- * $Id: packet-portmap.c,v 1.24 2001/01/28 03:39:48 guy Exp $
+ * $Id: packet-portmap.c,v 1.25 2001/02/06 06:46:10 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -65,175 +65,233 @@ static gint ett_portmap_entry = -1;
 
 
 /* Dissect a getport call */
-int dissect_getport_call(const u_char *pd, int offset, frame_data *fd,
+int dissect_getport_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
        guint32 proto;
        guint32 prog;
-       if ( !BYTES_ARE_IN_FRAME(offset, 16)) return offset;
 
        if ( tree )
        {
-               prog = pntohl(&pd[offset+0]);
-               proto_tree_add_uint_format(tree, hf_portmap_prog, NullTVB,
+               prog = tvb_get_ntohl(tvb, offset+0);
+               proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
                        offset, 4, prog, "Program: %s (%u)",
                        rpc_prog_name(prog), prog);
-               proto_tree_add_uint(tree, hf_portmap_version, NullTVB,
-                       offset+4, 4, pntohl(&pd[offset+4]));
+               proto_tree_add_item(tree, hf_portmap_version, tvb,
+                       offset+4, 4, FALSE);
 
-               proto = pntohl(&pd[offset+8]);
-               proto_tree_add_uint_format(tree, hf_portmap_proto, NullTVB,
+               proto = tvb_get_ntohl(tvb, offset+8);
+               proto_tree_add_uint_format(tree, hf_portmap_proto, tvb,
                        offset+8, 4, proto, "Proto: %s (%u)", ipprotostr(proto), proto);
 
-               proto_tree_add_uint(tree, hf_portmap_port, NullTVB,
-                       offset+12, 4, pntohl(&pd[offset+12]));
+               proto_tree_add_item(tree, hf_portmap_port, tvb,
+                       offset+12, 4, FALSE);
        }
        
        return offset+16;
 }
 
-int dissect_getport_reply(const u_char *pd, int offset, frame_data *fd,
+int dissect_getport_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       if ( !BYTES_ARE_IN_FRAME(offset, 4)) return offset;
-       if ( tree )
-       {
-               proto_tree_add_uint(tree, hf_portmap_port, NullTVB,
-                       offset, 4, pntohl(&pd[offset+0]));
-       }
-    return offset+=4;
+       offset = dissect_rpc_uint32_tvb(tvb, pinfo, tree, hf_portmap_port,
+           offset);
+       return offset;
 }
 
 /* Dissect a 'set' call */
-int dissect_set_call(const u_char *pd, int offset, frame_data *fd,
+int dissect_set_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
        guint32 proto;
        guint32 prog;
-       if ( !BYTES_ARE_IN_FRAME(offset, 16)) return offset;
 
        if ( tree )
        {
-               prog = pntohl(&pd[offset+0]);
-               proto_tree_add_uint_format(tree, hf_portmap_prog, NullTVB,
+               prog = tvb_get_ntohl(tvb, offset+0);
+               proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
                        offset, 4, prog, "Program: %s (%d)",
                        rpc_prog_name(prog), prog);
-               proto_tree_add_uint(tree, hf_portmap_version, NullTVB,
-                       offset+4, 4, pntohl(&pd[offset+4]));
+               proto_tree_add_item(tree, hf_portmap_version, tvb,
+                       offset+4, 4, FALSE);
 
-               proto = pntohl(&pd[offset+8]);
-               proto_tree_add_uint_format(tree, hf_portmap_proto, NullTVB,
+               proto = tvb_get_ntohl(tvb, offset+8);
+               proto_tree_add_uint_format(tree, hf_portmap_proto,tvb,
                        offset+8, 4, proto, "Proto: %s (%d)", ipprotostr(proto), proto);
 
-               proto_tree_add_uint(tree, hf_portmap_port, NullTVB,
-                       offset+12, 4, pntohl(&pd[offset+12]));
+               proto_tree_add_item(tree, hf_portmap_port, tvb,
+                       offset+12, 4, FALSE);
        }
        
        return offset+16;
 }
 
 /* Dissect a 'unset' call */
-int dissect_unset_call(const u_char *pd, int offset, frame_data *fd,
+int dissect_unset_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
        guint32 proto;
        guint32 prog;
-       if ( !BYTES_ARE_IN_FRAME(offset, 16)) return offset;
 
        if ( tree )
        {
-               prog = pntohl(&pd[offset+0]);
-               proto_tree_add_uint_format(tree, hf_portmap_prog, NullTVB,
+               prog = tvb_get_ntohl(tvb, offset+0);
+               proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
                        offset, 4, prog, "Program: %s (%d)",
                        rpc_prog_name(prog), prog);
-               proto_tree_add_uint(tree, hf_portmap_version, NullTVB,
-                       offset+4, 4, pntohl(&pd[offset+4]));
+               proto_tree_add_item(tree, hf_portmap_version, tvb,
+                       offset+4, 4, FALSE);
 
-               proto = pntohl(&pd[offset+8]);
-               proto_tree_add_uint(tree, hf_portmap_proto, NullTVB,
+               proto = tvb_get_ntohl(tvb, offset+8);
+               proto_tree_add_uint(tree, hf_portmap_proto, tvb,
                        offset+8, 4, proto);
 
-               proto_tree_add_uint(tree, hf_portmap_port, NullTVB,
-                       offset+12, 4, pntohl(&pd[offset+12]));
+               proto_tree_add_item(tree, hf_portmap_port, tvb,
+                       offset+12, 4, FALSE);
        }
-       
+
        return offset+16;
 }
 
-int dissect_set_reply(const u_char *pd, int offset, frame_data *fd,
+int dissect_set_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       if ( tree )
-       {
-               if ( !BYTES_ARE_IN_FRAME(offset, 4)) return offset;
-
-               proto_tree_add_boolean(tree, hf_portmap_answer, NullTVB,
-                       offset, 4, pntohl(&pd[offset+0]));
-               offset += 4;
-       }
-    return offset;
+       offset = dissect_rpc_bool_tvb(tvb, pinfo, tree, hf_portmap_answer,
+           offset);
+       return offset;
 }
 
 static int
-dissect_dump_entry(const u_char* pd, int offset, frame_data* fd, proto_tree* tree)
+dissect_dump_entry(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree)
 {
        int prog, version, proto, port;
        proto_item *ti, *subtree;
 
-       if ( ! BYTES_ARE_IN_FRAME(offset, 16) )
-       {
-               if ( tree )
-               {
-                       proto_tree_add_text(tree, NullTVB, offset, END_OF_FRAME, "Map Entry: <TRUNCATED>");
-               }
-               return pi.captured_len;
-       }
-       prog = pntohl(&pd[offset+0]);
-       version = pntohl(&pd[offset+4]);
-       proto = pntohl(&pd[offset+8]);
-       port = pntohl(&pd[offset+12]);
+       prog = tvb_get_ntohl(tvb, offset+0);
+       version = tvb_get_ntohl(tvb, offset+4);
+       proto = tvb_get_ntohl(tvb, offset+8);
+       port = tvb_get_ntohl(tvb, offset+12);
        if ( tree )
        {
-               ti = proto_tree_add_text(tree, NullTVB, offset, 16, "Map Entry: %s (%u) V%d",
+               ti = proto_tree_add_text(tree, tvb, offset, 16,
+                       "Map Entry: %s (%u) V%d",
                        rpc_prog_name(prog), prog, version);
                subtree = proto_item_add_subtree(ti, ett_portmap_entry);
 
-               proto_tree_add_uint_format(subtree, hf_portmap_prog, NullTVB,
+               proto_tree_add_uint_format(subtree, hf_portmap_prog, tvb,
                        offset+0, 4, prog,
                        "Program: %s (%u)", rpc_prog_name(prog), prog);
-               proto_tree_add_uint(subtree, hf_portmap_version, NullTVB,
+               proto_tree_add_uint(subtree, hf_portmap_version, tvb,
                        offset+4, 4, version);
-               proto_tree_add_uint_format(subtree, hf_portmap_proto, NullTVB,
+               proto_tree_add_uint_format(subtree, hf_portmap_proto, tvb,
                        offset+8, 4, proto, 
                        "Protocol: %s (0x%02x)", ipprotostr(proto), proto);
-               proto_tree_add_uint(subtree, hf_portmap_port, NullTVB,
+               proto_tree_add_uint(subtree, hf_portmap_port, tvb,
                        offset+12, 4, port);
        }
        offset += 16;
        return offset;
 }
 
-int dissect_dump_reply(const u_char *pd, int offset, frame_data *fd,
+int dissect_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_rpc_list(pd, offset, fd, tree, dissect_dump_entry);
+       offset = dissect_rpc_list_tvb(tvb, pinfo, tree, offset,
+               dissect_dump_entry);
        return offset;
 }
 
+/* Dissect a callit call */
+int dissect_callit_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
+       proto_tree *tree)
+{
+       rpc_proc_info_key key;
+       rpc_proc_info_value *value;
+       char *procname = NULL;
+       char procname_static[20];
+       old_dissect_function_t *old_dissect_function = NULL;
+       dissect_function_t *dissect_function = NULL;
+
+       key.prog = tvb_get_ntohl(tvb, offset+0);
+       if ( tree )
+       {
+               proto_tree_add_uint_format(tree, hf_portmap_prog, tvb,
+                       offset, 4, key.prog, "Program: %s (%u)",
+                       rpc_prog_name(key.prog), key.prog);
+       }
+
+       key.vers = tvb_get_ntohl(tvb, offset+4);
+       if ( tree )
+       {
+               proto_tree_add_uint(tree, hf_portmap_version, tvb,
+                       offset+4, 4, key.vers);
+       }
+
+       key.proc = tvb_get_ntohl(tvb, offset+8);
+       if ((value = g_hash_table_lookup(rpc_procs,&key)) != NULL) {
+               if (value->is_old_dissector)
+                       old_dissect_function = value->dissect_call.old;
+               else
+                       dissect_function = value->dissect_call.new;
+               procname = value->name;
+       }
+       else {
+               /* happens only with strange program versions or
+                  non-existing dissectors */
+#if 0
+               dissect_function = NULL;
+#endif
+               sprintf(procname_static, "proc-%u", key.proc);
+               procname = procname_static;
+       }
+       if ( tree )
+       {
+               proto_tree_add_uint_format(tree, hf_portmap_proc, tvb,
+                       offset+8, 4, key.proc, "Procedure: %s (%u)",
+                       procname, key.proc);
+       }
+
+       if ( tree )
+       {
+               proto_tree_add_text(tree, tvb, offset+12, 4,
+                       "Argument length: %u",
+                       tvb_get_ntohl(tvb, offset+12));
+       }
+
+       offset += 16;
+
+       /* Call the call dissector to dissect the opaque arguments.
+          Make the columns non-writable, so it won't change them out
+          from under us. */
+       col_set_writable(pinfo->fd, FALSE);
+       offset = call_dissect_function(tvb, pinfo, tree, offset,
+                       old_dissect_function, dissect_function, NULL);
+
+       return offset;
+}
+
+/*
+ * XXX - to dissect a CALLIT reply, we'd need to somehow associate
+ * the program/version/procedure information we get on a call with
+ * the RPC dissector's information about the call, and get that
+ * information from the reply dissector.
+ */
+
 /* proc number, "proc name", dissect_request, dissect_reply */
 /* NULL as function pointer means: type of arguments is "void". */
-static const old_vsff portmap1_proc[] = {
-       { PORTMAPPROC_NULL,     "NULL",         NULL,                           NULL },
-       { PORTMAPPROC_SET,      "SET",          NULL,                           NULL },
-       { PORTMAPPROC_UNSET,    "UNSET",                NULL,                           NULL },
-       { PORTMAPPROC_GETPORT,  "GETPORT",              NULL,                           NULL },
-       { PORTMAPPROC_DUMP,     "DUMP",         NULL,                           NULL },
-       { PORTMAPPROC_CALLIT,   "CALLIT",               NULL,                           NULL },
-       { 0,    NULL,           NULL,                           NULL }
+static const vsff portmap1_proc[] = {
+       { PORTMAPPROC_NULL,     "NULL",         NULL,   NULL },
+       { PORTMAPPROC_SET,      "SET",          NULL,   NULL },
+       { PORTMAPPROC_UNSET,    "UNSET",        NULL,   NULL },
+       { PORTMAPPROC_GETPORT,  "GETPORT",      NULL,   NULL },
+       { PORTMAPPROC_DUMP,     "DUMP",         NULL,   NULL },
+       { PORTMAPPROC_CALLIT,   "CALLIT",       NULL,   NULL },
+       { 0,                    NULL,           NULL,   NULL }
 };
 /* end of Portmap version 1 */
 
-static const old_vsff portmap2_proc[] = {
+static const vsff portmap2_proc[] = {
        { PORTMAPPROC_NULL, "NULL",
                NULL, NULL },
        { PORTMAPPROC_SET, "SET",
@@ -245,47 +303,43 @@ static const old_vsff portmap2_proc[] = {
        { PORTMAPPROC_DUMP, "DUMP",
                NULL, dissect_dump_reply },
        { PORTMAPPROC_CALLIT, "CALLIT",
-               NULL, NULL },
-    { 0, NULL, NULL, NULL }
+               dissect_callit_call, NULL },
+       { 0, NULL, NULL, NULL }
 };
 /* end of Portmap version 2 */
 
 
 /* RFC 1833, Page 3 */
 static int
-dissect_rpcb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
+dissect_rpcb(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
 {
        proto_item* rpcb_item = NULL;
        proto_tree* rpcb_tree = NULL;
        int old_offset = offset;
        guint32 prog;
-       guint32 version;
 
        if (tree) {
-               rpcb_item = proto_tree_add_item(tree, hf_portmap_rpcb, NullTVB,
-                       offset+0, END_OF_FRAME, FALSE);
+               rpcb_item = proto_tree_add_item(tree, hf_portmap_rpcb, tvb,
+                       offset, tvb_length(tvb), FALSE);
                if (rpcb_item)
                        rpcb_tree = proto_item_add_subtree(rpcb_item, ett_portmap_rpcb);
        }
 
-       if (!BYTES_ARE_IN_FRAME(offset, 4)) return offset;
-       prog = EXTRACT_UINT(pd, offset + 0);
+       prog = tvb_get_ntohl(tvb, offset);
        if (rpcb_tree)
-               proto_tree_add_uint_format(rpcb_tree, hf_portmap_rpcb_prog, NullTVB,
-                       offset+0, 4, prog, 
+               proto_tree_add_uint_format(rpcb_tree, hf_portmap_rpcb_prog, tvb,
+                       offset, 4, prog, 
                        "Program: %s (%u)", rpc_prog_name(prog), prog);
        offset += 4;
 
-       if (!BYTES_ARE_IN_FRAME(offset, 4)) return offset;
-       version = EXTRACT_UINT(pd, offset + 0);
-       if (rpcb_tree)
-               proto_tree_add_uint(rpcb_tree, hf_portmap_rpcb_version, NullTVB,
-                       offset+0, 4, version);
-       offset += 4;
-
-       offset = dissect_rpc_string(pd, offset, fd, rpcb_tree, hf_portmap_rpcb_netid,NULL);
-       offset = dissect_rpc_string(pd, offset, fd, rpcb_tree, hf_portmap_rpcb_addr,NULL);
-       offset = dissect_rpc_string(pd, offset, fd, rpcb_tree, hf_portmap_rpcb_owner,NULL);
+       offset = dissect_rpc_uint32_tvb(tvb, pinfo, rpcb_tree,
+           hf_portmap_rpcb_version, offset);
+       offset = dissect_rpc_string_tvb(tvb, pinfo, rpcb_tree,
+           hf_portmap_rpcb_netid, offset, NULL);
+       offset = dissect_rpc_string_tvb(tvb, pinfo, rpcb_tree,
+           hf_portmap_rpcb_addr, offset, NULL);
+       offset = dissect_rpc_string_tvb(tvb, pinfo, rpcb_tree,
+           hf_portmap_rpcb_owner, offset, NULL);
 
        /* now we know, that rpcb is shorter */
        if (rpcb_item) {
@@ -298,36 +352,37 @@ dissect_rpcb(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
 
 
 /* RFC 1833, Page 7 */
-int dissect_rpcb3_getaddr_call(const u_char *pd, int offset, frame_data *fd,
+int dissect_rpcb3_getaddr_call(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_rpcb(pd, offset, fd, tree);
+       offset = dissect_rpcb(tvb, offset, pinfo, tree);
 
        return offset;
 }
 
 
 /* RFC 1833, Page 7 */
-int dissect_rpcb3_getaddr_reply(const u_char *pd, int offset, frame_data *fd,
+int dissect_rpcb3_getaddr_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_rpc_string(pd, offset, fd, tree, hf_portmap_uaddr,NULL);
+       offset = dissect_rpc_string_tvb(tvb, pinfo, tree,
+           hf_portmap_uaddr, offset, NULL);
 
        return offset;
 }
 
 
 /* RFC 1833, Page 7 */
-int dissect_rpcb3_dump_reply(const u_char *pd, int offset, frame_data *fd,
+int dissect_rpcb3_dump_reply(tvbuff_t *tvb, int offset, packet_info *pinfo,
        proto_tree *tree)
 {
-       offset = dissect_rpc_list(pd, offset, fd, tree, dissect_rpcb);
+       offset = dissect_rpc_list_tvb(tvb, pinfo, tree, offset, dissect_rpcb);
        return offset;
 }
 
 
 /* Portmapper version 3, RFC 1833, Page 7 */
-static const old_vsff portmap3_proc[] = {
+static const vsff portmap3_proc[] = {
        { RPCBPROC_NULL,        "NULL",
                NULL, NULL },
        { RPCBPROC_SET,         "SET",
@@ -352,7 +407,7 @@ static const old_vsff portmap3_proc[] = {
 
 
 /* Portmapper version 4, RFC 1833, Page 8 */
-static const old_vsff portmap4_proc[] = {
+static const vsff portmap4_proc[] = {
        { RPCBPROC_NULL,        "NULL",
                NULL, NULL },
        { RPCBPROC_SET,         "SET",
@@ -444,8 +499,8 @@ proto_reg_handoff_portmap(void)
        /* Register the protocol as RPC */
        rpc_init_prog(proto_portmap, PORTMAP_PROGRAM, ett_portmap);
        /* Register the procedure tables */
-       old_rpc_init_proc_table(PORTMAP_PROGRAM, 1, portmap1_proc);
-       old_rpc_init_proc_table(PORTMAP_PROGRAM, 2, portmap2_proc);
-       old_rpc_init_proc_table(PORTMAP_PROGRAM, 3, portmap3_proc);
-       old_rpc_init_proc_table(PORTMAP_PROGRAM, 4, portmap4_proc);
+       rpc_init_proc_table(PORTMAP_PROGRAM, 1, portmap1_proc);
+       rpc_init_proc_table(PORTMAP_PROGRAM, 2, portmap2_proc);
+       rpc_init_proc_table(PORTMAP_PROGRAM, 3, portmap3_proc);
+       rpc_init_proc_table(PORTMAP_PROGRAM, 4, portmap4_proc);
 }
index ed40de8668a9584c8c7d8829d71b9057512771b5..2b9ac66d08d35c86856922b6e340edab44c7e0b8 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for rpc dissection
  * Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
  * 
- * $Id: packet-rpc.c,v 1.51 2001/01/28 03:39:48 guy Exp $
+ * $Id: packet-rpc.c,v 1.52 2001/02/06 06:46:10 guy Exp $
  * 
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@zing.org>
@@ -178,26 +178,7 @@ static gint ett_rpc_gss_data = -1;
 static GHashTable *rpc_progs;
 
 /* Hash table with info on RPC procedure numbers */
-static GHashTable *rpc_procs;
-
-typedef struct _rpc_proc_info_key {
-       guint32 prog;
-       guint32 vers;
-       guint32 proc;
-} rpc_proc_info_key;
-
-typedef struct _rpc_proc_info_value {
-       gchar           *name;
-       gboolean        is_old_dissector;
-       union {
-               old_dissect_function_t *old;
-               dissect_function_t *new;
-       } dissect_call;
-       union {
-               old_dissect_function_t *old;
-               dissect_function_t *new;
-       } dissect_reply;
-} rpc_proc_info_value;
+GHashTable *rpc_procs;
 
 typedef struct _rpc_prog_info_key {
        guint32 prog;
@@ -209,7 +190,6 @@ typedef struct _rpc_prog_info_value {
        char* progname;
 } rpc_prog_info_value;
 
-
 /***********************************/
 /* Hash array with procedure names */
 /***********************************/
@@ -1008,7 +988,7 @@ dissect_rpc_authgss_initres(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree,
 }
 
 
-static int
+int
 call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        int offset, old_dissect_function_t *old_dissect_function,
        dissect_function_t* dissect_function, const char *progname)
@@ -1018,7 +998,8 @@ call_dissect_function(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        if (old_dissect_function != NULL || dissect_function != NULL) {
                /* set the current protocol name */
                saved_proto = pinfo->current_proto;
-               pinfo->current_proto = progname;
+               if (progname != NULL)
+                       pinfo->current_proto = progname;
 
                /* call the dissector for the next level */
                if (dissect_function == NULL) {
index 6c8dcbf56da772f600dd0f241b39e29281bf9fca..1f3db02932c1f006d911ef1206abf07914c34b66 100644 (file)
@@ -1,6 +1,6 @@
 /* packet-rpc.h
  *
- * $Id: packet-rpc.h,v 1.23 2001/01/28 03:39:48 guy Exp $
+ * $Id: packet-rpc.h,v 1.24 2001/02/06 06:46:10 guy Exp $
  *
  * (c) 1999 Uwe Girlich
  *
@@ -88,12 +88,41 @@ typedef struct _vsff {
        dissect_function_t *dissect_reply;
 } vsff;
 
+/*
+ * These are used by the CALLIT handler for the portmapper dissector.
+ */
+typedef struct _rpc_proc_info_key {
+       guint32 prog;
+       guint32 vers;
+       guint32 proc;
+} rpc_proc_info_key;
+
+typedef struct _rpc_proc_info_value {
+       gchar           *name;
+       gboolean        is_old_dissector;
+       union {
+               old_dissect_function_t *old;
+               dissect_function_t *new;
+       } dissect_call;
+       union {
+               old_dissect_function_t *old;
+               dissect_function_t *new;
+       } dissect_reply;
+} rpc_proc_info_value;
+
+/* Hash table with info on RPC procedure numbers */
+GHashTable *rpc_procs;
+
 extern const value_string rpc_auth_flavor[];
 
 extern void old_rpc_init_proc_table(guint prog, guint vers, const old_vsff *proc_table);
 extern void rpc_init_proc_table(guint prog, guint vers, const vsff *proc_table);
 extern void rpc_init_prog(int proto, guint32 prog, int ett);
 extern char *rpc_prog_name(guint32 prog);
+extern int call_dissect_function(tvbuff_t *tvb, packet_info *pinfo,
+       proto_tree *tree, int offset,
+       old_dissect_function_t *old_dissect_function,
+       dissect_function_t* dissect_function, const char *progname);
 
 extern unsigned int rpc_roundup(unsigned int a);
 extern int dissect_rpc_bool(const u_char *pd, int offset, frame_data *fd,