Use ENC_NA as encoding for proto_tree_add_item() calls which directly reference an...
[obnox/wireshark/wip.git] / epan / dissectors / packet-rpc.c
index dce81ce5afc6c8a866940038e262a64f3bd184d7..3895923263375f5b37935ecaf2a8bb66559a0a75 100644 (file)
@@ -30,7 +30,6 @@
 #endif
 
 #include <glib.h>
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include <epan/packet.h>
@@ -80,8 +79,6 @@ static gboolean rpc_dissect_unknown_programs = FALSE;
  */
 static gboolean rpc_find_fragment_start = FALSE;
 
-static struct true_false_string yesno = { "Yes", "No" };
-
 static int rpc_tap = -1;
 
 static const value_string rpc_msg_type[] = {
@@ -132,7 +129,7 @@ static const value_string rpc_authgssapi_proc[] = {
        { 0, NULL }
 };
 
-value_string rpc_authgss_svc[] = {
+const value_string rpc_authgss_svc[] = {
        { RPCSEC_GSS_SVC_NONE, "rpcsec_gss_svc_none" },
        { RPCSEC_GSS_SVC_INTEGRITY, "rpcsec_gss_svc_integrity" },
        { RPCSEC_GSS_SVC_PRIVACY, "rpcsec_gss_svc_privacy" },
@@ -205,6 +202,7 @@ static int hf_rpc_authgss_window = -1;
 static int hf_rpc_authgss_token_length = -1;
 static int hf_rpc_authgss_data_length = -1;
 static int hf_rpc_authgss_data = -1;
+static int hf_rpc_authgss_token = -1;
 static int hf_rpc_authgss_checksum = -1;
 static int hf_rpc_authgssapi_v = -1;
 static int hf_rpc_authgssapi_msg = -1;
@@ -236,6 +234,8 @@ static int hf_rpc_fragment_overlap_conflict = -1;
 static int hf_rpc_fragment_multiple_tails = -1;
 static int hf_rpc_fragment_too_long_fragment = -1;
 static int hf_rpc_fragment_error = -1;
+static int hf_rpc_fragment_count = -1;
+static int hf_rpc_reassembled_length = -1;
 
 static gint ett_rpc = -1;
 static gint ett_rpc_unknown_program = -1;
@@ -256,7 +256,7 @@ static dissector_handle_t rpc_handle;
 static dissector_handle_t gssapi_handle;
 static dissector_handle_t data_handle;
 
-static guint max_rpc_tcp_pdu_size = 262144;
+static guint max_rpc_tcp_pdu_size = 4 * 1024 * 1024;
 
 static const fragment_items rpc_frag_items = {
        &ett_rpc_fragment,
@@ -268,7 +268,9 @@ static const fragment_items rpc_frag_items = {
        &hf_rpc_fragment_multiple_tails,
        &hf_rpc_fragment_too_long_fragment,
        &hf_rpc_fragment_error,
+       &hf_rpc_fragment_count,
        NULL,
+       &hf_rpc_reassembled_length,
        "fragments"
 };
 
@@ -355,7 +357,6 @@ rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
        rpc_proc_info_value *value;
        char *procname;
 
-       procname=ep_alloc(20);
        key.prog = prog;
        key.vers = vers;
        key.proc = proc;
@@ -365,7 +366,7 @@ rpc_proc_name(guint32 prog, guint32 vers, guint32 proc)
        else {
                /* happens only with strange program versions or
                   non-existing dissectors */
-               g_snprintf(procname, 20, "proc-%u", key.proc);
+               procname = ep_strdup_printf("proc-%u", key.proc);
        }
        return procname;
 }
@@ -424,7 +425,8 @@ rpc_init_prog(int proto, guint32 prog, int ett)
 
 /*     return the hf_field associated with a previously registered program.
 */
-int rpc_prog_hf(guint32 prog, guint32 vers)
+int
+rpc_prog_hf(guint32 prog, guint32 vers)
 {
        rpc_prog_info_key       rpc_prog_key;
        rpc_prog_info_value     *rpc_prog;
@@ -439,7 +441,8 @@ int rpc_prog_hf(guint32 prog, guint32 vers)
 /*     return the name associated with a previously registered program. This
        should probably eventually be expanded to use the rpc YP/NIS map
        so that it can give names for programs not handled by wireshark */
-const char *rpc_prog_name(guint32 prog)
+const char *
+rpc_prog_name(guint32 prog)
 {
        const char *progname = NULL;
        rpc_prog_info_key       rpc_prog_key;
@@ -483,7 +486,7 @@ rpc_roundup(unsigned int a)
 
 int
 dissect_rpc_bool(tvbuff_t *tvb, proto_tree *tree,
-int hfindex, int offset)
+                int hfindex, int offset)
 {
        if (tree)
                proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
@@ -493,7 +496,7 @@ int hfindex, int offset)
 
 int
 dissect_rpc_uint32(tvbuff_t *tvb, proto_tree *tree,
-int hfindex, int offset)
+                  int hfindex, int offset)
 {
        if (tree)
                proto_tree_add_item(tree, hfindex, tvb, offset, 4, FALSE);
@@ -503,7 +506,7 @@ int hfindex, int offset)
 
 int
 dissect_rpc_uint64(tvbuff_t *tvb, proto_tree *tree,
-int hfindex, int offset)
+                  int hfindex, int offset)
 {
        header_field_info       *hfinfo;
 
@@ -611,9 +614,7 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
         }
 
        if (string_data) {
-               char *tmpstr;
-               tmpstr = tvb_get_ephemeral_string(tvb, data_offset, string_length_copy);
-               string_buffer = memcpy(ep_alloc(string_length_copy+1), tmpstr, string_length_copy);
+               string_buffer = tvb_get_ephemeral_string(tvb, data_offset, string_length_copy);
        } else {
                string_buffer = tvb_memcpy(tvb, ep_alloc(string_length_copy+1), data_offset, string_length_copy);
        }
@@ -625,24 +626,21 @@ dissect_rpc_opaque_data(tvbuff_t *tvb, int offset,
                                char *formatted;
 
                                formatted = format_text(string_buffer, strlen(string_buffer));
-                               /* alloc maximum data area */
-#define STRING_BUFFER_PRINT_MAX_LEN (strlen(formatted)+12+1)
-                               string_buffer_print = (char*)ep_alloc(STRING_BUFFER_PRINT_MAX_LEN);
                                /* copy over the data and append <TRUNCATED> */
-                               g_snprintf(string_buffer_print, STRING_BUFFER_PRINT_MAX_LEN, "%s<TRUNCATED>", formatted);
+                               string_buffer_print=ep_strdup_printf("%s%s", formatted, RPC_STRING_TRUNCATED);
                        } else {
-                               string_buffer_print="<DATA><TRUNCATED>";
+                               string_buffer_print=RPC_STRING_DATA RPC_STRING_TRUNCATED;
                        }
                } else {
                        if (string_data) {
                                string_buffer_print =
                                    ep_strdup(format_text(string_buffer, strlen(string_buffer)));
                        } else {
-                               string_buffer_print="<DATA>";
+                               string_buffer_print=RPC_STRING_DATA;
                        }
                }
        } else {
-               string_buffer_print="<EMPTY>";
+               string_buffer_print=RPC_STRING_EMPTY;
        }
 
        if (tree) {
@@ -888,7 +886,7 @@ dissect_rpc_authgss_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
 
 static int
 dissect_rpc_authdes_desblock(tvbuff_t *tvb, proto_tree *tree,
-int hfindex, int offset)
+                            int hfindex, int offset)
 {
        guint32 value_low;
        guint32 value_high;
@@ -1027,7 +1025,7 @@ dissect_rpc_cred(tvbuff_t* tvb, proto_tree* tree, int offset)
  */
 static int
 dissect_rpc_authgss_token(tvbuff_t* tvb, proto_tree* tree, int offset,
-    packet_info *pinfo)
+    packet_info *pinfo, int hfindex)
 {
        guint32 opaque_length, rounded_length;
        gint len_consumed, length, reported_length;
@@ -1039,8 +1037,7 @@ dissect_rpc_authgss_token(tvbuff_t* tvb, proto_tree* tree, int offset,
        opaque_length = tvb_get_ntohl(tvb, offset+0);
        rounded_length = rpc_roundup(opaque_length);
        if (tree) {
-               gitem = proto_tree_add_text(tree, tvb, offset,
-                                           4+rounded_length, "GSS Token");
+               gitem = proto_tree_add_item(tree, hfindex, tvb, offset, 4+rounded_length, FALSE);
                gtree = proto_item_add_subtree(gitem, ett_rpc_gss_token);
                proto_tree_add_uint(gtree, hf_rpc_authgss_token_length,
                                    tvb, offset+0, 4, opaque_length);
@@ -1122,7 +1119,7 @@ dissect_rpc_verf(tvbuff_t* tvb, proto_tree* tree, int offset, int msg_type,
                        }
                        break;
                case RPCSEC_GSS:
-                       dissect_rpc_authgss_token(tvb, vtree, offset+4, pinfo);
+                       dissect_rpc_authgss_token(tvb, vtree, offset+4, pinfo, hf_rpc_authgss_token);
                        break;
                default:
                        proto_tree_add_uint(vtree, hf_rpc_auth_length, tvb,
@@ -1142,7 +1139,7 @@ static int
 dissect_rpc_authgss_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
     packet_info *pinfo)
 {
-       return dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
+       return dissect_rpc_authgss_token(tvb, tree, offset, pinfo, hf_rpc_authgss_token);
 }
 
 static int
@@ -1172,7 +1169,7 @@ dissect_rpc_authgss_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
                                    offset+0, 4, window);
        offset += 4;
 
-       offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo);
+       offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo, hf_rpc_authgss_token);
 
        return offset;
 }
@@ -1197,7 +1194,7 @@ dissect_rpc_authgssapi_initarg(tvbuff_t* tvb, proto_tree* tree, int offset,
        }
        offset += 4;
 
-       offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
+       offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo, hf_rpc_authgss_token);
 
        return offset;
 }
@@ -1241,7 +1238,7 @@ dissect_rpc_authgssapi_initres(tvbuff_t* tvb, proto_tree* tree, int offset,
        }
        offset += 4;
 
-       offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo);
+       offset = dissect_rpc_authgss_token(tvb, mtree, offset, pinfo, hf_rpc_authgss_token);
 
        offset = dissect_rpc_data(tvb, mtree, hf_rpc_authgssapi_isn, offset);
 
@@ -1312,8 +1309,8 @@ dissect_rpc_authgss_integ_data(tvbuff_t *tvb, packet_info *pinfo,
                                      dissect_function, progname);
        }
        offset += rounded_length - 4;
-       offset = dissect_rpc_data(tvb, tree, hf_rpc_authgss_checksum,
-                       offset);
+       offset = dissect_rpc_authgss_token(tvb, tree, offset, pinfo, hf_rpc_authgss_checksum);
+
        return offset;
 }
 
@@ -1569,16 +1566,14 @@ dissect_rpc_indir_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                        procname = (char *)rpc_call->proc_info->name;
                }
                else {
-                       procname=ep_alloc(20);
-                       g_snprintf(procname, 20, "proc-%u", rpc_call->proc);
+                       procname=ep_strdup_printf("proc-%u", rpc_call->proc);
                }
        }
        else {
 #if 0
                dissect_function = NULL;
 #endif
-               procname=ep_alloc(20);
-               g_snprintf(procname, 20, "proc-%u", rpc_call->proc);
+               procname=ep_strdup_printf("proc-%u", rpc_call->proc);
        }
 
        if ( tree )
@@ -1631,10 +1626,8 @@ dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        proto_item *rpc_item;
        proto_tree *rpc_tree;
 
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
-       if (check_col(pinfo->cinfo, COL_INFO))
-               col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
+       col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
 
        if (tree) {
                rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
@@ -1650,19 +1643,15 @@ dissect_rpc_continuation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  *  and version values.
  */
 
-static void  make_fake_rpc_prog_if_needed (rpc_prog_info_key *prpc_prog_key,
-                                                                                                                guint prog_ver)
+static void
+make_fake_rpc_prog_if_needed (rpc_prog_info_key *prpc_prog_key, guint prog_ver)
 {
-
-rpc_prog_info_value *rpc_prog = NULL;
-
-
        /* sanity check: no one uses versions > 10 */
        if(prog_ver>10){
                return;
        }
 
-       if( (rpc_prog = g_hash_table_lookup(rpc_progs, prpc_prog_key)) == NULL) {
+       if(g_hash_table_lookup(rpc_progs, prpc_prog_key) == NULL) {
                /* ok this is not a known rpc program so we
                 * will have to fake it.
                 */
@@ -1673,12 +1662,9 @@ rpc_prog_info_value *rpc_prog = NULL;
                        { 0,NULL,NULL,NULL }
                };
 
-               NAME=g_malloc(36);
-               Name=g_malloc(32);
-               name=g_malloc(32);
-               g_snprintf(NAME, 36, "Unknown RPC Program:%d",prpc_prog_key->prog);
-               g_snprintf(Name, 32, "RPC:%d",prpc_prog_key->prog);
-               g_snprintf(name, 32, "rpc%d",prpc_prog_key->prog);
+               NAME = g_strdup_printf("Unknown RPC Program:%d",prpc_prog_key->prog);
+               Name = g_strdup_printf("RPC:%d",prpc_prog_key->prog);
+               name = g_strdup_printf("rpc%d",prpc_prog_key->prog);
                proto_rpc_unknown_program = proto_register_protocol(NAME, Name, name);
 
                rpc_init_prog(proto_rpc_unknown_program, prpc_prog_key->prog, ett_rpc_unknown_program);
@@ -1738,7 +1724,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
        nstime_t ns;
 
        dissect_function_t *dissect_function = NULL;
-       gboolean dissect_rpc = TRUE;
+       gboolean dissect_rpc_flag = TRUE;
 
        rpc_conv_info_t *rpc_conv_info=NULL;
 
@@ -1934,8 +1920,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                }
        }
 
-       if (check_col(pinfo->cinfo, COL_PROTOCOL))
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
 
        if (tree) {
                rpc_item = proto_tree_add_item(tree, proto_rpc, tvb, 0, -1,
@@ -1987,11 +1972,9 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                "Program: %s (%u)", progname, prog);
                }
 
-               if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
-                       /* Set the protocol name to the underlying
-                          program name. */
-                       col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
-               }
+               /* Set the protocol name to the underlying
+                  program name. */
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
 
                vers = tvb_get_ntohl(tvb, offset+8);
                if (rpc_tree) {
@@ -2015,8 +1998,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 #if 0
                        dissect_function = NULL;
 #endif
-                       procname=ep_alloc(20);
-                       g_snprintf(procname, 20, "proc-%u", proc);
+                       procname=ep_strdup_printf("proc-%u", proc);
                }
 
                /* Check for RPCSEC_GSS and AUTH_GSSAPI */
@@ -2055,8 +2037,8 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                                flavor = FLAVOR_AUTHGSSAPI_MSG;
                                                gss_proc = proc;
                                                procname = (char *)
-                                                   match_strval(gss_proc,
-                                                   rpc_authgssapi_proc);
+                                                   val_to_str(gss_proc,
+                                                   rpc_authgssapi_proc, "Unknown (%d)");
                                        } else {
                                                flavor = FLAVOR_AUTHGSSAPI;
                                        }
@@ -2078,16 +2060,18 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                "Procedure: %s (%u)", procname, proc);
                }
 
-               if (check_col(pinfo->cinfo, COL_INFO)) {
-                       if (first_pdu)
-                               col_clear(pinfo->cinfo, COL_INFO);
-                       else
-                               col_append_str(pinfo->cinfo, COL_INFO, "  ; ");
+               /* Print the program version, procedure name, and message type (call or reply). */
+               if (first_pdu)
+                       col_clear(pinfo->cinfo, COL_INFO);
+               else
+                       col_append_str(pinfo->cinfo, COL_INFO, "  ; ");
+               /* Special case for NFSv4 - if the type is COMPOUND, do not print the procedure name */
+               if (vers==4 && prog==NFS_PROGRAM && !strcmp(procname, "COMPOUND"))
+                       col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s", vers,
+                                       msg_type_name);
+               else
                        col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s",
-                               vers,
-                               procname,
-                               msg_type_name);
-               }
+                                       vers, procname, msg_type_name);
 
                /* Keep track of the address whence the call came, and the
                   port to which the call is being sent, so that we can
@@ -2166,19 +2150,16 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                        if (pinfo->fd->num != rpc_call->req_num) {
                                /* No, so it's a duplicate request.
                                   Mark it as such. */
-                               if (check_col(pinfo->cinfo, COL_INFO)) {
-                                       col_prepend_fstr(pinfo->cinfo, COL_INFO,
-                                               "[RPC retransmission of #%d]", rpc_call->req_num);
-                               }
-                               proto_tree_add_item(rpc_tree,
-                                       hf_rpc_dup, tvb, 0,0, TRUE);
-                               proto_tree_add_uint(rpc_tree,
-                                       hf_rpc_call_dup, tvb, 0,0, rpc_call->req_num);
+                               col_prepend_fstr(pinfo->cinfo, COL_INFO,
+                                                "[RPC retransmission of #%d]",
+                                                rpc_call->req_num);
+                               proto_tree_add_item(rpc_tree, hf_rpc_dup, tvb,
+                                                   0, 0, ENC_NA);
+                               proto_tree_add_uint(rpc_tree, hf_rpc_call_dup,
+                                                   tvb, 0,0, rpc_call->req_num);
                        }
                        if(rpc_call->rep_num){
-                               if (check_col(pinfo->cinfo, COL_INFO)) {
-                                       col_append_fstr(pinfo->cinfo, COL_INFO," (Reply In %d)", rpc_call->rep_num);
-                               }
+                               col_append_fstr(pinfo->cinfo, COL_INFO," (Reply In %d)", rpc_call->rep_num);
                        }
                } else {
                        /* Prepare the value data.
@@ -2243,16 +2224,14 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                procname = (char *)rpc_call->proc_info->name;
                        }
                        else {
-                               procname=ep_alloc(20);
-                               g_snprintf(procname, 20, "proc-%u", proc);
+                               procname=ep_strdup_printf("proc-%u", proc);
                        }
                }
                else {
 #if 0
                        dissect_function = NULL;
 #endif
-                       procname=ep_alloc(20);
-                       g_snprintf(procname, 20, "proc-%u", proc);
+                       procname=ep_strdup_printf("proc-%u", proc);
                }
 
                /*
@@ -2263,7 +2242,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                 * AUTH_GSSAPI procname.
                 */
                if (flavor == FLAVOR_AUTHGSSAPI_MSG) {
-                       procname = (char *)match_strval(gss_proc, rpc_authgssapi_proc);
+                       procname = (char *)val_to_str_const(gss_proc, rpc_authgssapi_proc, "(null)");
                }
 
                rpc_prog_key.prog = prog;
@@ -2279,23 +2258,23 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                        ett = rpc_prog->ett;
                        progname = rpc_prog->progname;
 
-                       if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
-                               /* Set the protocol name to the underlying
-                                  program name. */
-                               col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
-                       }
+                       /* Set the protocol name to the underlying
+                          program name. */
+                       col_set_str(pinfo->cinfo, COL_PROTOCOL, progname);
                }
 
-               if (check_col(pinfo->cinfo, COL_INFO)) {
-                       if (first_pdu)
-                               col_clear(pinfo->cinfo, COL_INFO);
-                       else
-                               col_append_str(pinfo->cinfo, COL_INFO, "  ; ");
+               /* Print the program version, procedure name, and message type (call or reply). */
+               if (first_pdu)
+                       col_clear(pinfo->cinfo, COL_INFO);
+               else
+                       col_append_str(pinfo->cinfo, COL_INFO, "  ; ");
+               /* Special case for NFSv4 - if the type is COMPOUND, do not print the procedure name */
+               if (vers==4 && prog==NFS_PROGRAM && !strcmp(procname, "COMPOUND"))
+                       col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s",
+                                       vers, msg_type_name);
+               else
                        col_append_fstr(pinfo->cinfo, COL_INFO,"V%u %s %s",
-                               vers,
-                               procname,
-                               msg_type_name);
-               }
+                                       vers, procname, msg_type_name);
 
                if (rpc_tree) {
                        proto_item *tmp_item;
@@ -2334,9 +2313,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                &ns);
                        PROTO_ITEM_SET_GENERATED(tmp_item);
 
-                       if (check_col(pinfo->cinfo, COL_INFO)) {
-                               col_append_fstr(pinfo->cinfo, COL_INFO," (Call In %d)", rpc_call->req_num);
-                       }
+                       col_append_fstr(pinfo->cinfo, COL_INFO," (Call In %d)", rpc_call->req_num);
                }
 
 
@@ -2353,12 +2330,10 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
 
                                /* No, so it's a duplicate reply.
                                   Mark it as such. */
-                               if (check_col(pinfo->cinfo, COL_INFO)) {
-                                       col_prepend_fstr(pinfo->cinfo, COL_INFO,
+                               col_prepend_fstr(pinfo->cinfo, COL_INFO,
                                                "[RPC duplicate of #%d]", rpc_call->rep_num);
-                               }
                                tmp_item=proto_tree_add_item(rpc_tree,
-                                       hf_rpc_dup, tvb, 0,0, TRUE);
+                                       hf_rpc_dup, tvb, 0,0, ENC_NA);
                                PROTO_ITEM_SET_GENERATED(tmp_item);
 
                                tmp_item=proto_tree_add_uint(rpc_tree,
@@ -2400,7 +2375,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                 * There's no protocol reply, so don't
                                 * try to dissect it.
                                 */
-                               dissect_rpc = FALSE;
+                               dissect_rpc_flag = FALSE;
                                break;
 
                        default:
@@ -2408,7 +2383,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                                 * There's no protocol reply, so don't
                                 * try to dissect it.
                                 */
-                               dissect_rpc = FALSE;
+                               dissect_rpc_flag = FALSE;
                                break;
                        }
                        break;
@@ -2448,7 +2423,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                         * There's no protocol reply, so don't
                         * try to dissect it.
                         */
-                       dissect_rpc = FALSE;
+                       dissect_rpc_flag = FALSE;
                        break;
 
                default:
@@ -2457,7 +2432,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                         * no clue what's going on; don't try to dissect
                         * the protocol reply.
                         */
-                       dissect_rpc = FALSE;
+                       dissect_rpc_flag = FALSE;
                        break;
                }
                break; /* end of RPC reply */
@@ -2478,16 +2453,23 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                proto_item_set_end(rpc_item, tvb, offset);
        }
 
-       if (!dissect_rpc) {
+       if (!dissect_rpc_flag) {
                /*
                 * There's no RPC call or reply here; just dissect
                 * whatever's left as data.
                 */
                call_dissector(data_handle,
-                   tvb_new_subset(tvb, offset, -1, -1), pinfo, rpc_tree);
+                   tvb_new_subset_remaining(tvb, offset), pinfo, rpc_tree);
                return TRUE;
        }
 
+       /* we must queue this packet to the tap system before we actually
+          call the subdissectors since short packets (i.e. nfs read reply)
+          will cause an exception and execution would never reach the call
+          to tap_queue_packet() in that case
+       */
+       tap_queue_packet(rpc_tap, pinfo, rpc_call);
+
        /* create here the program specific sub-tree */
        if (tree && (flavor != FLAVOR_AUTHGSSAPI_MSG)) {
                pitem = proto_tree_add_item(tree, proto_id, tvb, offset, -1,
@@ -2523,18 +2505,18 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                }
        }
 
-       /* we must queue this packet to the tap system before we actually
-          call the subdissectors since short packets (i.e. nfs read reply)
-          will cause an exception and execution would never reach the call
-          to tap_queue_packet() in that case
-       */
-       tap_queue_packet(rpc_tap, pinfo, rpc_call);
-
        /* proto==0 if this is an unknown program */
        if( (proto==0) || !proto_is_protocol_enabled(proto)){
                dissect_function = NULL;
        }
 
+        /*
+         * Don't call any subdissector if we have no more date to dissect.
+         */
+        if (tvb_length_remaining(tvb, offset) == 0) {
+                return TRUE;
+        }
+
        /*
         * Handle RPCSEC_GSS and AUTH_GSSAPI specially.
         */
@@ -2620,16 +2602,12 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                 * protocol and info fields to indicate that this is
                 * an RPC auth level message, then process the args.
                 */
-               if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
-                       col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
-               }
-               if (check_col(pinfo->cinfo, COL_INFO)) {
-                       col_clear(pinfo->cinfo, COL_INFO);
-                       col_append_fstr(pinfo->cinfo, COL_INFO,
-                           "%s %s XID 0x%x",
-                           match_strval(gss_proc, rpc_authgssapi_proc),
-                           msg_type_name, xid);
-               }
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPC");
+               col_clear(pinfo->cinfo, COL_INFO);
+               col_append_fstr(pinfo->cinfo, COL_INFO,
+                               "%s %s XID 0x%x",
+                               val_to_str(gss_proc, rpc_authgssapi_proc, "Unknown (%d)"),
+                               msg_type_name, xid);
 
                switch (gss_proc) {
 
@@ -2676,7 +2654,7 @@ dissect_rpc_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
            */
 
           call_dissector(data_handle,
-              tvb_new_subset(tvb, offset, -1, -1), pinfo, ptree);
+              tvb_new_subset_remaining(tvb, offset), pinfo, ptree);
         }
 
        /* XXX this should really loop over all fhandles registred for the frame */
@@ -2728,6 +2706,7 @@ typedef struct _rpc_fragment_key {
        guint32 conv_id;
        guint32 seq;
        guint32 offset;
+       guint32 port;
        /* xxx */
        guint32 start_seq;
 } rpc_fragment_key;
@@ -2747,7 +2726,7 @@ rpc_fragment_equal(gconstpointer k1, gconstpointer k2)
        const rpc_fragment_key *key2 = (const rpc_fragment_key *)k2;
 
        return key1->conv_id == key2->conv_id &&
-           key1->seq == key2->seq;
+           key1->seq == key2->seq && key1->port == key2->port;
 }
 
 static void
@@ -2839,6 +2818,7 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
 {
        const char *saved_proto;
        volatile gboolean rpc_succeeded;
+       void *pd_save;
 
        /*
         * Catch the ReportedBoundsError exception; if
@@ -2853,6 +2833,7 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
         */
        saved_proto = pinfo->current_proto;
        rpc_succeeded = FALSE;
+       pd_save = pinfo->private_data;
        TRY {
                rpc_succeeded = (*dissector)(rec_tvb, pinfo, tree,
                    frag_tvb, ipfd_head, TRUE, rpc_rm, first_pdu);
@@ -2864,6 +2845,12 @@ call_message_dissector(tvbuff_t *tvb, tvbuff_t *rec_tvb, packet_info *pinfo,
                show_reported_bounds_error(tvb, pinfo, tree);
                pinfo->current_proto = saved_proto;
 
+               /*  Restore the private_data structure in case one of the
+                *  called dissectors modified it (and, due to the exception,
+                *  was unable to restore it).
+                */
+               pinfo->private_data = pd_save;
+
                /*
                 * We treat this as a "successful" dissection of
                 * an RPC packet, as "dissect_rpc_message()"
@@ -3028,6 +3015,7 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }
        old_rfk.conv_id = conversation->index;
        old_rfk.seq = seq;
+        old_rfk.port = pinfo->srcport;
        rfk = g_hash_table_lookup(rpc_reassembly_table, &old_rfk);
 
        if (rfk == NULL) {
@@ -3068,6 +3056,7 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        rfk = se_alloc(sizeof(rpc_fragment_key));
                        rfk->conv_id = conversation->index;
                        rfk->seq = seq;
+                       rfk->port = pinfo->srcport;
                        rfk->offset = 0;
                        rfk->start_seq = seq;
                        g_hash_table_insert(rpc_reassembly_table, rfk, rfk);
@@ -3089,6 +3078,7 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
                                new_rfk = se_alloc(sizeof(rpc_fragment_key));
                                new_rfk->conv_id = rfk->conv_id;
                                new_rfk->seq = seq + len;
+                               new_rfk->port = pinfo->srcport;
                                new_rfk->offset = rfk->offset + len - 4;
                                new_rfk->start_seq = rfk->start_seq;
                                g_hash_table_insert(rpc_reassembly_table, new_rfk,
@@ -3154,6 +3144,7 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
                        new_rfk = se_alloc(sizeof(rpc_fragment_key));
                        new_rfk->conv_id = rfk->conv_id;
                        new_rfk->seq = seq + len;
+                        new_rfk->port = pinfo->srcport;
                        new_rfk->offset = rfk->offset + len - 4;
                        new_rfk->start_seq = rfk->start_seq;
                        g_hash_table_insert(rpc_reassembly_table, new_rfk,
@@ -3216,15 +3207,9 @@ dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
                 * Create a new TVB structure for
                 * defragmented data.
                 */
-               rec_tvb = tvb_new_real_data(ipfd_head->data,
+               rec_tvb = tvb_new_child_real_data(tvb, ipfd_head->data,
                    ipfd_head->datalen, ipfd_head->datalen);
 
-               /*
-                * Add this tvb as a child to the original
-                * one.
-                */
-               tvb_set_child_real_data_tvbuff(tvb, rec_tvb);
-
                /*
                 * Add defragmented data to the data source list.
                 */
@@ -3256,63 +3241,63 @@ static int
 find_rpc_over_tcp_reply_start(tvbuff_t *tvb, int offset)
 {
 
-/*
- * Looking for partial header sequence.  From beginning of
- * stream-style header, including "record mark", full ONC-RPC
- * looks like:
- *    BE int32    record mark (rfc 1831 sec. 10)
- *    ?  int32    XID (rfc 1831 sec. 8)
- *    BE int32    msg_type (ibid sec. 8, call = 0, reply = 1)
- *
- * -------------------------------------------------------------
- * Then reply-specific fields are
- *    BE int32    reply_stat (ibid, accept = 0, deny = 1)
- *
- * Then, assuming accepted,
- *   opaque_auth
- *    BE int32    auth_flavor (ibid, none = 0)
- *    BE int32    ? auth_len (ibid, none = 0)
- *
- *    BE int32    accept_stat (ibid, success = 0, errs are 1..5 in rpc v2)
- *
- * -------------------------------------------------------------
- * Or, call-specific fields are
- *    BE int32    rpc_vers (rfc 1831 sec 8, always == 2)
- *    BE int32    prog (NFS == 000186A3)
- *    BE int32    prog_ver (NFS v2/3 == 2 or 3)
- *    BE int32    proc_id (NFS, <= 256 ???)
- *   opaque_auth
- *    ...
- */
+       /*
       * Looking for partial header sequence.  From beginning of
       * stream-style header, including "record mark", full ONC-RPC
       * looks like:
       *    BE int32    record mark (rfc 1831 sec. 10)
       *    ?  int32    XID (rfc 1831 sec. 8)
       *    BE int32    msg_type (ibid sec. 8, call = 0, reply = 1)
       *
       * -------------------------------------------------------------
       * Then reply-specific fields are
       *    BE int32    reply_stat (ibid, accept = 0, deny = 1)
       *
       * Then, assuming accepted,
       *   opaque_auth
       *    BE int32    auth_flavor (ibid, none = 0)
       *    BE int32    ? auth_len (ibid, none = 0)
       *
       *    BE int32    accept_stat (ibid, success = 0, errs are 1..5 in rpc v2)
       *
       * -------------------------------------------------------------
       * Or, call-specific fields are
       *    BE int32    rpc_vers (rfc 1831 sec 8, always == 2)
       *    BE int32    prog (NFS == 000186A3)
       *    BE int32    prog_ver (NFS v2/3 == 2 or 3)
       *    BE int32    proc_id (NFS, <= 256 ???)
       *   opaque_auth
       *    ...
       */
 
-/* Initially, we search only for something matching the template
- * of a successful reply with no auth verifier.
- * Our first qualification test is search for a string of zero bytes,
- * corresponding the four guint32 values
- *    reply_stat
- *    auth_flavor
- *    auth_len
- *    accept_stat
- *
- * If this string of zeros matches, then we go back and check the
- * preceding msg_type and record_mark fields.
- */
+       /* Initially, we search only for something matching the template
       * of a successful reply with no auth verifier.
       * Our first qualification test is search for a string of zero bytes,
       * corresponding the four guint32 values
       *    reply_stat
       *    auth_flavor
       *    auth_len
       *    accept_stat
       *
       * If this string of zeros matches, then we go back and check the
       * preceding msg_type and record_mark fields.
       */
 
-const gint     cbZeroTail = 4 * 4;     /* four guint32s of zeros */
-const gint     ibPatternStart = 3 * 4;    /* offset of zero fill from reply start */
-const guint8 * pbWholeBuf;    /* all of tvb, from offset onwards */
-const int      NoMatch = -1;
+       const gint     cbZeroTail = 4 * 4;     /* four guint32s of zeros */
+       const gint     ibPatternStart = 3 * 4;    /* offset of zero fill from reply start */
+       const guint8 * pbWholeBuf;    /* all of tvb, from offset onwards */
+       const int      NoMatch = -1;
 
-gint     ibSearchStart;       /* offset of search start, in case of false hits. */
+       gint     ibSearchStart;       /* offset of search start, in case of false hits. */
 
-const    guint8 * pbBuf;
+       const    guint8 * pbBuf;
 
-gint     cbInBuf;       /* bytes in tvb, from offset onwards */
+       gint     cbInBuf;       /* bytes in tvb, from offset onwards */
 
-guint32  ulMsgType;
-guint32  ulRecMark;
+       guint32  ulMsgType;
+       guint32  ulRecMark;
 
-int      i;
+       int      i;
 
 
        cbInBuf = tvb_reported_length_remaining(tvb, offset);
@@ -3391,9 +3376,9 @@ int      i;
 
 static int
 find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
-                                                         proto_tree *tree, rec_dissector_t dissector,
-                                                         gboolean is_heur,
-                                                         int proto, int ett, gboolean defragment)
+                             proto_tree *tree, rec_dissector_t dissector,
+                             gboolean is_heur,
+                             int proto, int ett, gboolean defragment)
 {
 
        int   offReply;
@@ -3407,16 +3392,16 @@ find_and_dissect_rpc_fragment(tvbuff_t *tvb, int offset, packet_info *pinfo,
        }
 
        len = dissect_rpc_fragment(tvb, offReply,
-                                                          pinfo, tree,
-                                                          dissector, is_heur, proto, ett,
-                                                          defragment,
-                                                          TRUE /* force first-pdu state */);
+                                  pinfo, tree,
+                                  dissector, is_heur, proto, ett,
+                                  defragment,
+                                  TRUE /* force first-pdu state */);
 
        /* misses are reported as-is */
        if (len == 0)
-               {
+       {
                return (0);
-               }
+       }
 
        /* returning a non-zero length, correct it to reflect the extra offset
         * we found necessary
@@ -3494,6 +3479,14 @@ dissect_rpc_tcp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                        break;
                }
 
+               /*  Set a fence so whatever the subdissector put in the
+                *  Info column stays there.  This is useful when the
+                *  subdissector clears the column (which it might have to do
+                *  if it runs over some other protocol too) and there are
+                *  multiple PDUs in one frame.
+                */
+               col_set_fence(pinfo->cinfo, COL_INFO);
+
                /* PDU tracking
                  If the length indicates that the PDU continues beyond
                  the end of this tvb, then tell TCP about it so that it
@@ -3561,166 +3554,169 @@ proto_register_rpc(void)
        static hf_register_info hf[] = {
                { &hf_rpc_reqframe, {
                        "Request Frame", "rpc.reqframe", FT_FRAMENUM, BASE_NONE,
-                       NULL, 0, "Request Frame", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_repframe, {
                        "Reply Frame", "rpc.repframe", FT_FRAMENUM, BASE_NONE,
-                       NULL, 0, "Reply Frame", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_lastfrag, {
                        "Last Fragment", "rpc.lastfrag", FT_BOOLEAN, 32,
-                       &yesno, RPC_RM_LASTFRAG, "Last Fragment", HFILL }},
+                       TFS(&tfs_yes_no), RPC_RM_LASTFRAG, NULL, HFILL }},
                { &hf_rpc_fraglen, {
                        "Fragment Length", "rpc.fraglen", FT_UINT32, BASE_DEC,
-                       NULL, RPC_RM_FRAGLEN, "Fragment Length", HFILL }},
+                       NULL, RPC_RM_FRAGLEN, NULL, HFILL }},
                { &hf_rpc_xid, {
                        "XID", "rpc.xid", FT_UINT32, BASE_HEX,
-                       NULL, 0, "XID", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_msgtype, {
                        "Message Type", "rpc.msgtyp", FT_UINT32, BASE_DEC,
-                       VALS(rpc_msg_type), 0, "Message Type", HFILL }},
+                       VALS(rpc_msg_type), 0, NULL, HFILL }},
                { &hf_rpc_state_reply, {
                        "Reply State", "rpc.replystat", FT_UINT32, BASE_DEC,
-                       VALS(rpc_reply_state), 0, "Reply State", HFILL }},
+                       VALS(rpc_reply_state), 0, NULL, HFILL }},
                { &hf_rpc_state_accept, {
                        "Accept State", "rpc.state_accept", FT_UINT32, BASE_DEC,
-                       VALS(rpc_accept_state), 0, "Accept State", HFILL }},
+                       VALS(rpc_accept_state), 0, NULL, HFILL }},
                { &hf_rpc_state_reject, {
                        "Reject State", "rpc.state_reject", FT_UINT32, BASE_DEC,
-                       VALS(rpc_reject_state), 0, "Reject State", HFILL }},
+                       VALS(rpc_reject_state), 0, NULL, HFILL }},
                { &hf_rpc_state_auth, {
                        "Auth State", "rpc.state_auth", FT_UINT32, BASE_DEC,
-                       VALS(rpc_auth_state), 0, "Auth State", HFILL }},
+                       VALS(rpc_auth_state), 0, NULL, HFILL }},
                { &hf_rpc_version, {
                        "RPC Version", "rpc.version", FT_UINT32, BASE_DEC,
-                       NULL, 0, "RPC Version", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_version_min, {
                        "RPC Version (Minimum)", "rpc.version.min", FT_UINT32,
                        BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
                { &hf_rpc_version_max, {
                        "RPC Version (Maximum)", "rpc.version.max", FT_UINT32,
-                       BASE_DEC, NULL, 0, "RPC Version (Maximum)", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_program, {
                        "Program", "rpc.program", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Program", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_programversion, {
                        "Program Version", "rpc.programversion", FT_UINT32,
-                       BASE_DEC, NULL, 0, "Program Version", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_programversion_min, {
                        "Program Version (Minimum)", "rpc.programversion.min", FT_UINT32,
-                       BASE_DEC, NULL, 0, "Program Version (Minimum)", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_programversion_max, {
                        "Program Version (Maximum)", "rpc.programversion.max", FT_UINT32,
-                       BASE_DEC, NULL, 0, "Program Version (Maximum)", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_procedure, {
                        "Procedure", "rpc.procedure", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Procedure", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_auth_flavor, {
                        "Flavor", "rpc.auth.flavor", FT_UINT32, BASE_DEC,
-                       VALS(rpc_auth_flavor), 0, "Flavor", HFILL }},
+                       VALS(rpc_auth_flavor), 0, NULL, HFILL }},
                { &hf_rpc_auth_length, {
                        "Length", "rpc.auth.length", FT_UINT32, BASE_DEC,
-                       NULL, 0, "Length", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_auth_stamp, {
                        "Stamp", "rpc.auth.stamp", FT_UINT32, BASE_HEX,
-                       NULL, 0, "Stamp", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_auth_uid, {
                        "UID", "rpc.auth.uid", FT_UINT32, BASE_DEC,
-                       NULL, 0, "UID", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_auth_gid, {
                        "GID", "rpc.auth.gid", FT_UINT32, BASE_DEC,
-                       NULL, 0, "GID", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_v, {
                        "GSS Version", "rpc.authgss.version", FT_UINT32,
-                       BASE_DEC, NULL, 0, "GSS Version", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_proc, {
                        "GSS Procedure", "rpc.authgss.procedure", FT_UINT32,
-                       BASE_DEC, VALS(rpc_authgss_proc), 0, "GSS Procedure", HFILL }},
+                       BASE_DEC, VALS(rpc_authgss_proc), 0, NULL, HFILL }},
                { &hf_rpc_authgss_seq, {
                        "GSS Sequence Number", "rpc.authgss.seqnum", FT_UINT32,
-                       BASE_DEC, NULL, 0, "GSS Sequence Number", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_svc, {
                        "GSS Service", "rpc.authgss.service", FT_UINT32,
-                       BASE_DEC, VALS(rpc_authgss_svc), 0, "GSS Service", HFILL }},
+                       BASE_DEC, VALS(rpc_authgss_svc), 0, NULL, HFILL }},
                { &hf_rpc_authgss_ctx, {
                        "GSS Context", "rpc.authgss.context", FT_BYTES,
-                       BASE_HEX, NULL, 0, "GSS Context", HFILL }},
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_major, {
                        "GSS Major Status", "rpc.authgss.major", FT_UINT32,
-                       BASE_DEC, NULL, 0, "GSS Major Status", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_minor, {
                        "GSS Minor Status", "rpc.authgss.minor", FT_UINT32,
-                       BASE_DEC, NULL, 0, "GSS Minor Status", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_window, {
                        "GSS Sequence Window", "rpc.authgss.window", FT_UINT32,
-                       BASE_DEC, NULL, 0, "GSS Sequence Window", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_token_length, {
                        "GSS Token Length", "rpc.authgss.token_length", FT_UINT32,
-                       BASE_DEC, NULL, 0, "GSS Token Length", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_data_length, {
                        "Length", "rpc.authgss.data.length", FT_UINT32,
-                       BASE_DEC, NULL, 0, "Length", HFILL }},
+                       BASE_DEC, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_data, {
                        "GSS Data", "rpc.authgss.data", FT_BYTES,
-                       BASE_HEX, NULL, 0, "GSS Data", HFILL }},
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgss_checksum, {
                        "GSS Checksum", "rpc.authgss.checksum", FT_BYTES,
-                       BASE_HEX, NULL, 0, "GSS Checksum", HFILL }},
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
+               { &hf_rpc_authgss_token, {
+                       "GSS Token", "rpc.authgss.token", FT_BYTES,
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgssapi_v, {
                        "AUTH_GSSAPI Version", "rpc.authgssapi.version",
-                       FT_UINT32, BASE_DEC, NULL, 0, "AUTH_GSSAPI Version",
+                       FT_UINT32, BASE_DEC, NULL, 0, NULL,
                        HFILL }},
                { &hf_rpc_authgssapi_msg, {
                        "AUTH_GSSAPI Message", "rpc.authgssapi.message",
-                       FT_BOOLEAN, BASE_NONE, &yesno, 0, "AUTH_GSSAPI Message",
+                       FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0x0, NULL,
                        HFILL }},
                { &hf_rpc_authgssapi_msgv, {
                        "Msg Version", "rpc.authgssapi.msgversion",
-                       FT_UINT32, BASE_DEC, NULL, 0, "Msg Version",
+                       FT_UINT32, BASE_DEC, NULL, 0, NULL,
                        HFILL }},
                { &hf_rpc_authgssapi_handle, {
                        "Client Handle", "rpc.authgssapi.handle",
-                       FT_BYTES, BASE_HEX, NULL, 0, "Client Handle", HFILL }},
+                       FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authgssapi_isn, {
                        "Signed ISN", "rpc.authgssapi.isn",
-                       FT_BYTES, BASE_HEX, NULL, 0, "Signed ISN", HFILL }},
+                       FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authdes_namekind, {
                        "Namekind", "rpc.authdes.namekind", FT_UINT32, BASE_DEC,
-                       VALS(rpc_authdes_namekind), 0, "Namekind", HFILL }},
+                       VALS(rpc_authdes_namekind), 0, NULL, HFILL }},
                { &hf_rpc_authdes_netname, {
                        "Netname", "rpc.authdes.netname", FT_STRING,
-                       BASE_DEC, NULL, 0, "Netname", HFILL }},
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authdes_convkey, {
                        "Conversation Key (encrypted)", "rpc.authdes.convkey", FT_UINT32,
-                       BASE_HEX, NULL, 0, "Conversation Key (encrypted)", HFILL }},
+                       BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authdes_window, {
                        "Window (encrypted)", "rpc.authdes.window", FT_UINT32,
                        BASE_HEX, NULL, 0, "Windows (encrypted)", HFILL }},
                { &hf_rpc_authdes_nickname, {
                        "Nickname", "rpc.authdes.nickname", FT_UINT32,
-                       BASE_HEX, NULL, 0, "Nickname", HFILL }},
+                       BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authdes_timestamp, {
                        "Timestamp (encrypted)", "rpc.authdes.timestamp", FT_UINT32,
-                       BASE_HEX, NULL, 0, "Timestamp (encrypted)", HFILL }},
+                       BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authdes_windowverf, {
                        "Window verifier (encrypted)", "rpc.authdes.windowverf", FT_UINT32,
-                       BASE_HEX, NULL, 0, "Window verifier (encrypted)", HFILL }},
+                       BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_rpc_authdes_timeverf, {
                        "Timestamp verifier (encrypted)", "rpc.authdes.timeverf", FT_UINT32,
-                       BASE_HEX, NULL, 0, "Timestamp verifier (encrypted)", HFILL }},
+                       BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_rpc_auth_machinename, {
                        "Machine Name", "rpc.auth.machinename", FT_STRING,
-                       BASE_DEC, NULL, 0, "Machine Name", HFILL }},
+                       BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_rpc_dup, {
                        "Duplicate Call/Reply", "rpc.dup", FT_NONE, BASE_NONE,
-                       NULL, 0, "Duplicate Call/Reply", HFILL }},
+                       NULL, 0, NULL, HFILL }},
                { &hf_rpc_call_dup, {
-                       "Duplicate to the call in", "rpc.call.dup", FT_FRAMENUM, BASE_DEC,
+                       "Duplicate to the call in", "rpc.call.dup", FT_FRAMENUM, BASE_NONE,
                        NULL, 0, "This is a duplicate to the call in frame", HFILL }},
                { &hf_rpc_reply_dup, {
-                       "Duplicate to the reply in", "rpc.reply.dup", FT_FRAMENUM, BASE_DEC,
+                       "Duplicate to the reply in", "rpc.reply.dup", FT_FRAMENUM, BASE_NONE,
                        NULL, 0, "This is a duplicate to the reply in frame", HFILL }},
                { &hf_rpc_value_follows, {
                        "Value Follows", "rpc.value_follows", FT_BOOLEAN, BASE_NONE,
-                       &yesno, 0, "Value Follows", HFILL }},
+                       TFS(&tfs_yes_no), 0x0, NULL, HFILL }},
                { &hf_rpc_array_len, {
                        "num", "rpc.array.len", FT_UINT32, BASE_DEC,
                        NULL, 0, "Length of RPC array", HFILL }},
@@ -3749,13 +3745,21 @@ proto_register_rpc(void)
                { "Defragmentation error", "rpc.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
                        "Defragmentation error due to illegal fragments", HFILL }},
 
+               { &hf_rpc_fragment_count,
+               { "Fragment count", "rpc.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       NULL, HFILL }},
+
                { &hf_rpc_fragment,
                { "RPC Fragment", "rpc.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
-                       "RPC Fragment", HFILL }},
+                       NULL, HFILL }},
 
                { &hf_rpc_fragments,
                { "RPC Fragments", "rpc.fragments", FT_NONE, BASE_NONE, NULL, 0x0,
-                       "RPC Fragments", HFILL }},
+                       NULL, HFILL }},
+
+               { &hf_rpc_reassembled_length,
+               { "Reassembled RPC length", "rpc.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x0,
+                       "The total length of the reassembled payload", HFILL }},
        };
        static gint *ett[] = {
                &ett_rpc,
@@ -3809,9 +3813,7 @@ proto_register_rpc(void)
                &rpc_find_fragment_start);
 
        register_dissector("rpc", dissect_rpc, proto_rpc);
-       rpc_handle = find_dissector("rpc");
        register_dissector("rpc-tcp", dissect_rpc_tcp, proto_rpc);
-       rpc_tcp_handle = find_dissector("rpc-tcp");
        rpc_tap = register_tap("rpc");
 
        /*
@@ -3832,9 +3834,6 @@ proto_register_rpc(void)
 void
 proto_reg_handoff_rpc(void)
 {
-       dissector_handle_t rpc_tcp_handle;
-       dissector_handle_t rpc_udp_handle;
-
        /* tcp/udp port 111 is used by portmapper which is an onc-rpc service.
           we register onc-rpc on this port so that we can choose RPC in
           the list offered by DecodeAs, and so that traffic to or from
@@ -3843,10 +3842,10 @@ proto_reg_handoff_rpc(void)
           probably RPC traffic from some randomly-chosen port that happens
           to match some port for which we have a dissector)
        */
-       rpc_tcp_handle = create_dissector_handle(dissect_rpc_tcp, proto_rpc);
-       dissector_add("tcp.port", 111, rpc_tcp_handle);
-       rpc_udp_handle = create_dissector_handle(dissect_rpc, proto_rpc);
-       dissector_add("udp.port", 111, rpc_udp_handle);
+       rpc_tcp_handle = find_dissector("rpc-tcp");
+       dissector_add_uint("tcp.port", 111, rpc_tcp_handle);
+       rpc_handle = find_dissector("rpc");
+       dissector_add_uint("udp.port", 111, rpc_handle);
 
        heur_dissector_add("tcp", dissect_rpc_tcp_heur, proto_rpc);
        heur_dissector_add("udp", dissect_rpc_heur, proto_rpc);
@@ -3860,10 +3859,10 @@ proto_reg_handoff_rpc(void)
  * Local Variables:
  * c-basic-offset: 8
  * tab-width: 8
- * indent-tabs-mode: tabs
+ * indent-tabs-mode: t
  * End:
  *
- * ex: set shiftwidth=8 tabstop=8 noexpandtab
+ * ex: set shiftwidth=8 tabstop=8 noexpandtab:
  * :indentSize=8:tabSize=8:noTabs=false:
  */