aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2001-01-18 00:13:18 +0000
committerGuy Harris <guy@alum.mit.edu>2001-01-18 00:13:18 +0000
commitd3512a34afde4a6a01e55e2db5c5d6f7c6204560 (patch)
tree31debd251cb5882261f3fcfe358438d802218700
parentbb2b650c9b788b2fa4d207b0e2f1a7d575462993 (diff)
Well, I found that one of my captures was so large that we overflowed
the static table of RPC calls and responses; this meant that, in some cases, I could click on a reply packet and it'd just be shown as a UDP packet in the protocol tree window, but if I then click on the matching request and click on the reply again, it'll show it as an RPC reply to the call in question. Replace the static table with a GHashTable, which grows as necessary. svn path=/trunk/; revision=2912
-rw-r--r--packet-rpc.c156
1 files changed, 81 insertions, 75 deletions
diff --git a/packet-rpc.c b/packet-rpc.c
index d3662b3879..d41b0898e2 100644
--- a/packet-rpc.c
+++ b/packet-rpc.c
@@ -2,7 +2,7 @@
* Routines for rpc dissection
* Copyright 1999, Uwe Girlich <Uwe.Girlich@philosys.de>
*
- * $Id: packet-rpc.c,v 1.47 2001/01/09 06:31:41 guy Exp $
+ * $Id: packet-rpc.c,v 1.48 2001/01/18 00:13:18 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@@ -304,10 +304,14 @@ char *rpc_prog_name(guint32 prog)
/* end of Hash array with program names */
/*--------------------------------------*/
-/* static array, first quick implementation, I'll switch over to GList soon */
-typedef struct _rpc_call_info {
+typedef struct _rpc_call_info_key {
guint32 xid;
conversation_t *conversation;
+} rpc_call_info_key;
+
+static GMemChunk *rpc_call_info_key_chunk;
+
+typedef struct _rpc_call_info_value {
guint32 req_num; /* frame number of first request seen */
guint32 rep_num; /* frame number of first reply seen */
guint32 prog;
@@ -317,58 +321,31 @@ typedef struct _rpc_call_info {
guint32 gss_proc;
guint32 gss_svc;
rpc_proc_info_value* proc_info;
-} rpc_call_info;
+} rpc_call_info_value;
-#define RPC_CALL_TABLE_LENGTH 1000
+static GMemChunk *rpc_call_info_value_chunk;
-rpc_call_info rpc_call_table[RPC_CALL_TABLE_LENGTH];
-guint32 rpc_call_index = 0;
-guint32 rpc_call_firstfree = 0;
+static GHashTable *rpc_calls;
-static void
-rpc_call_insert(rpc_call_info *call)
+/* compare 2 keys */
+gint
+rpc_call_equal(gconstpointer k1, gconstpointer k2)
{
- /* some space left? */
- if (rpc_call_firstfree<RPC_CALL_TABLE_LENGTH) {
- /* some space left */
- /* take the first free entry */
- rpc_call_index = rpc_call_firstfree;
- /* increase this limit */
- rpc_call_firstfree++;
- /* rpc_call_firstfree may now be RPC_CALL_TABLE_LENGTH */
- }
- else {
- /* no space left */
- /* the next entry, with wrap around */
- rpc_call_index = (rpc_call_index+1) % rpc_call_firstfree;
- }
-
- /* put the entry in */
- memcpy(&rpc_call_table[rpc_call_index],call,sizeof(*call));
- return;
+ rpc_call_info_key* key1 = (rpc_call_info_key*) k1;
+ rpc_call_info_key* key2 = (rpc_call_info_key*) k2;
+
+ return (key1->xid == key2->xid &&
+ key1->conversation == key2->conversation);
}
-static rpc_call_info*
-rpc_call_lookup(rpc_call_info *call)
+/* calculate a hash key */
+guint
+rpc_call_hash(gconstpointer k)
{
- int i;
-
- i = rpc_call_index;
- do {
- if (
- rpc_call_table[i].xid == call->xid &&
- rpc_call_table[i].conversation == call->conversation
- ) {
- return &rpc_call_table[i];
- }
- if (rpc_call_firstfree) {
- /* decrement by one, go to rpc_call_firstfree-1
- at the start of the list */
- i = (i-1+rpc_call_firstfree) % rpc_call_firstfree;
- }
- } while (i!=rpc_call_index);
- return NULL;
+ rpc_call_info_key* key = (rpc_call_info_key*) k;
+
+ return key->xid + (guint32)(key->conversation);
}
@@ -1050,8 +1027,8 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
int offset = 0;
guint32 msg_type;
- rpc_call_info rpc_key;
- rpc_call_info *rpc_call = NULL;
+ rpc_call_info_key rpc_call_key;
+ rpc_call_info_value *rpc_call = NULL;
rpc_prog_info_value *rpc_prog = NULL;
rpc_prog_info_key rpc_prog_key;
@@ -1090,7 +1067,7 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
int use_rm = 0;
guint32 rpc_rm = 0;
- rpc_call_info rpc_call_msg;
+ rpc_call_info_key *new_rpc_call_key;
rpc_proc_info_key key;
rpc_proc_info_value *value = NULL;
conversation_t* conversation;
@@ -1106,7 +1083,7 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* TCP uses record marking */
use_rm = (pinfo->ptype == PT_TCP);
- /* the first 4 bytes are special in "record marking mode" */
+ /* the first 4 bytes are special in "record marking mode" */
if (use_rm) {
if (!tvb_bytes_exist(tvb, offset, 4))
return FALSE;
@@ -1167,9 +1144,10 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
/* The XIDs of the call and reply must match. */
- rpc_key.xid = tvb_get_ntohl(tvb, offset + 0);
- rpc_key.conversation = conversation;
- if ((rpc_call = rpc_call_lookup(&rpc_key)) == NULL) {
+ rpc_call_key.xid = tvb_get_ntohl(tvb, offset + 0);
+ rpc_call_key.conversation = conversation;
+ rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
+ if (rpc_call == NULL) {
/* The XID doesn't match a call from that
conversation, so it's probably not an RPC reply. */
return FALSE;
@@ -1215,7 +1193,9 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset += 8;
- if (msg_type==RPC_CALL) {
+ switch (msg_type) {
+
+ case RPC_CALL:
/* we know already the proto-entry, the ETT-const,
and "rpc_prog" */
proto = rpc_prog->proto;
@@ -1310,11 +1290,12 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
/* prepare the key data */
- rpc_call_msg.xid = xid;
- rpc_call_msg.conversation = conversation;
+ rpc_call_key.xid = xid;
+ rpc_call_key.conversation = conversation;
/* look up the request */
- if ((rpc_call = rpc_call_lookup(&rpc_call_msg)) != NULL) {
+ rpc_call = g_hash_table_lookup(rpc_calls, &rpc_call_key);
+ if (rpc_call != NULL) {
/* We've seen a request with this XID, with the same
source and destination, before - but was it
*this* request? */
@@ -1339,17 +1320,21 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
frame numbers are 1-origin, so we use 0
to mean "we don't yet know in which frame
the reply for this call appears". */
- rpc_call_msg.req_num = pinfo->fd->num;
- rpc_call_msg.rep_num = 0;
- rpc_call_msg.prog = prog;
- rpc_call_msg.vers = vers;
- rpc_call_msg.proc = proc;
- rpc_call_msg.flavor = flavor;
- rpc_call_msg.gss_proc = gss_proc;
- rpc_call_msg.gss_svc = gss_svc;
- rpc_call_msg.proc_info = value;
+ new_rpc_call_key = g_mem_chunk_alloc(rpc_call_info_key_chunk);
+ *new_rpc_call_key = rpc_call_key;
+ rpc_call = g_mem_chunk_alloc(rpc_call_info_value_chunk);
+ rpc_call->req_num = pinfo->fd->num;
+ rpc_call->rep_num = 0;
+ rpc_call->prog = prog;
+ rpc_call->vers = vers;
+ rpc_call->proc = proc;
+ rpc_call->flavor = flavor;
+ rpc_call->gss_proc = gss_proc;
+ rpc_call->gss_svc = gss_svc;
+ rpc_call->proc_info = value;
/* store it */
- rpc_call_insert(&rpc_call_msg);
+ g_hash_table_insert(rpc_calls, new_rpc_call_key,
+ rpc_call);
}
offset += 16;
@@ -1359,9 +1344,9 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
/* go to the next dissector */
- } /* end of RPC call */
- else if (msg_type == RPC_REPLY)
- {
+ break; /* end of RPC call */
+
+ case RPC_REPLY:
/* we know already the type from the calling routine,
and we already have "rpc_call" set above. */
prog = rpc_call->prog;
@@ -1533,7 +1518,15 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
offset += 4;
}
}
- } /* end of RPC reply */
+ break; /* end of RPC reply */
+
+ default:
+ /*
+ * The switch statement at the top returned if
+ * this was neither an RPC call nor a reply.
+ */
+ g_assert_not_reached();
+ }
/* now we know, that RPC was shorter */
if (rpc_item) {
@@ -1613,9 +1606,22 @@ dissect_rpc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static void
rpc_init_protocol(void)
{
- memset(rpc_call_table, '\0', sizeof rpc_call_table);
- rpc_call_index = 0;
- rpc_call_firstfree = 0;
+ if (rpc_calls != NULL)
+ g_hash_table_destroy(rpc_calls);
+ if (rpc_call_info_key_chunk != NULL)
+ g_mem_chunk_destroy(rpc_call_info_key_chunk);
+ if (rpc_call_info_value_chunk != NULL)
+ g_mem_chunk_destroy(rpc_call_info_value_chunk);
+
+ rpc_calls = g_hash_table_new(rpc_call_hash, rpc_call_equal);
+ rpc_call_info_key_chunk = g_mem_chunk_new("call_info_key_chunk",
+ sizeof(rpc_call_info_key),
+ 200 * sizeof(rpc_call_info_key),
+ G_ALLOC_ONLY);
+ rpc_call_info_value_chunk = g_mem_chunk_new("call_info_value_chunk",
+ sizeof(rpc_call_info_value),
+ 200 * sizeof(rpc_call_info_value),
+ G_ALLOC_ONLY);
}