Instead of keeping in the information about an RPC call a count of the

number of replies seen, keep the frame number of the first request seen
for that call and the first reply seen for that call.  Use that to
determine whether a request or reply is a duplicate or not.

That means that we don't have to reset the table of RPC calls on a
rescan of the capture (which didn't even fix all the cases where we'd
have misreported the original call or reply as a duplicate due to having
seen it once on the initial pass through the file and once again when,
for example, the user clicked on the packet); doing so causes plenty of
other problems, so don't do that - and don't clear the "visited" flag on
frames on a rescan, either, as that's only done because we were clearing
out conversations and calling all protocols' "init" routines.

As a free bonus, this means that, for a reply, we know what frame the
request was in; put that information into the protocol tree for the
reply, snoop-style.

Make the table of RPC call information, and the routines that manipulate
it, static to "packet-rpc.c"; nobody outside "packet-rpc.c" uses them.

svn path=/trunk/; revision=2358
This commit is contained in:
Guy Harris 2000-08-24 06:19:53 +00:00
parent d93c1854b8
commit 47d5cfab52
3 changed files with 62 additions and 55 deletions

15
file.c
View File

@ -1,7 +1,7 @@
/* file.c
* File I/O routines
*
* $Id: file.c,v 1.209 2000/08/21 21:24:01 deniel Exp $
* $Id: file.c,v 1.210 2000/08/24 06:19:51 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -892,15 +892,6 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter)
rebuild the clist, however. */
selected_row = -1;
/* We need to re-initialize all the state information that protocols
keep, because we're making a fresh pass through all the packets. */
/* Initialize the table of conversations. */
conversation_init();
/* Initialize protocol-specific variables */
init_all_protocols();
/* Freeze the packet list while we redo it, so we don't get any
screen updates while it happens. */
gtk_clist_freeze(GTK_CLIST(packet_list));
@ -966,10 +957,6 @@ rescan_packets(capture_file *cf, const char *action, gboolean refilter)
count++;
/* Since all state for the frame was destroyed, mark the frame
* as not visited. */
fdata->flags.visited = 0;
wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header,
cf->pd, fdata->cap_len);

View File

@ -2,7 +2,7 @@
* Routines for rpc dissection
* Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
*
* $Id: packet-rpc.c,v 1.37 2000/08/14 07:47:19 girlich Exp $
* $Id: packet-rpc.c,v 1.38 2000/08/24 06:19:52 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -301,11 +301,27 @@ char *rpc_prog_name(guint32 prog)
/*--------------------------------------*/
/* static array, first quick implementation, I'll switch over to GList soon */
typedef struct _rpc_call_info {
guint32 xid;
conversation_t *conversation;
guint32 req_num; /* frame number of first request seen */
guint32 rep_num; /* frame number of first reply seen */
guint32 prog;
guint32 vers;
guint32 proc;
guint32 flavor;
guint32 gss_proc;
guint32 gss_svc;
rpc_proc_info_value* proc_info;
} rpc_call_info;
#define RPC_CALL_TABLE_LENGTH 1000
rpc_call_info rpc_call_table[RPC_CALL_TABLE_LENGTH];
guint32 rpc_call_index = 0;
guint32 rpc_call_firstfree = 0;
void
static void
rpc_call_insert(rpc_call_info *call)
{
/* some space left? */
@ -329,7 +345,7 @@ rpc_call_insert(rpc_call_info *call)
}
rpc_call_info*
static rpc_call_info*
rpc_call_lookup(rpc_call_info *call)
{
int i;
@ -1253,21 +1269,28 @@ dissect_rpc( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
rpc_call_msg.conversation = conversation;
/* look up the request */
if (rpc_call_lookup(&rpc_call_msg)) {
/* duplicate request */
if (check_col(fd, COL_INFO)) {
col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
if (rpc_tree) {
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_dup, NullTVB, 0,0, xid);
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_call_dup, NullTVB, 0,0, xid);
if ((rpc_call = rpc_call_lookup(&rpc_call_msg)) != NULL) {
/* We've seen a request with this XID, with the same
source and destination, before - but was it
*this* request? */
if (fd->num != rpc_call->req_num) {
/* No, so it's a duplicate request.
Mark it as such. */
if (check_col(fd, COL_INFO)) {
col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
if (rpc_tree) {
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_dup, NullTVB, 0,0, xid);
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_call_dup, NullTVB, 0,0, xid);
}
}
}
}
else {
/* prepare the value data */
rpc_call_msg.replies = 0;
rpc_call_msg.req_num = fd->num;
rpc_call_msg.rep_num = 0xffffffff;
rpc_call_msg.prog = prog;
rpc_call_msg.vers = vers;
rpc_call_msg.proc = proc;
@ -1298,6 +1321,11 @@ dissect_rpc( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
gss_proc = rpc_call->gss_proc;
gss_svc = rpc_call->gss_svc;
/* Indicate the frame to which this is a reply. */
proto_tree_add_text(rpc_tree, NullTVB, 0, 0,
"This is a reply to frame %u",
rpc_call->req_num);
if (rpc_call->proc_info != NULL) {
dissect_function = rpc_call->proc_info->dissect_reply;
if (rpc_call->proc_info->name != NULL) {
@ -1313,7 +1341,6 @@ dissect_rpc( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
sprintf(procname_static, "proc-%u", proc);
procname = procname_static;
}
rpc_call->replies++;
rpc_prog_key.prog = prog;
if ((rpc_prog = g_hash_table_lookup(rpc_progs,&rpc_prog_key)) == NULL) {
@ -1353,14 +1380,25 @@ dissect_rpc( const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
"Procedure: %s (%u)", procname, proc);
}
if (rpc_call->replies>1) {
if (check_col(fd, COL_INFO)) {
col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
if (rpc_tree) {
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_dup, NullTVB, 0,0, xid);
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_reply_dup, NullTVB, 0,0, xid);
if (rpc_call->rep_num == 0xffffffff) {
/* We have not yet seen a reply to that call, so
this must be the first reply; remember its
frame number. */
rpc_call->rep_num = fd->num;
} else {
/* We have seen a reply to this call - but was it
*this* reply? */
if (rpc_call->rep_num != fd->num) {
/* No, so it's a duplicate reply.
Mark it as such. */
if (check_col(fd, COL_INFO)) {
col_append_fstr(fd, COL_INFO, " dup XID 0x%x", xid);
if (rpc_tree) {
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_dup, NullTVB, 0,0, xid);
proto_tree_add_uint_hidden(rpc_tree,
hf_rpc_reply_dup, NullTVB, 0,0, xid);
}
}
}
}

View File

@ -1,6 +1,6 @@
/* packet-rpc.h
*
* $Id: packet-rpc.h,v 1.17 2000/08/11 13:34:01 deniel Exp $
* $Id: packet-rpc.h,v 1.18 2000/08/24 06:19:53 guy Exp $
*
* (c) 1999 Uwe Girlich
*
@ -102,26 +102,8 @@ typedef struct _rpc_prog_info_value {
char* progname;
} rpc_prog_info_value;
typedef struct _rpc_call_info {
guint32 xid;
conversation_t *conversation;
guint32 replies;
guint32 prog;
guint32 vers;
guint32 proc;
guint32 flavor;
guint32 gss_proc;
guint32 gss_svc;
rpc_proc_info_value* proc_info;
} rpc_call_info;
#define RPC_CALL_TABLE_LENGTH 1000
extern const value_string rpc_auth_flavor[];
extern void rpc_call_insert(rpc_call_info *call);
extern rpc_call_info* rpc_call_lookup(rpc_call_info *call);
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);