diff options
author | Guy Harris <guy@alum.mit.edu> | 2001-01-18 00:13:18 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2001-01-18 00:13:18 +0000 |
commit | d3512a34afde4a6a01e55e2db5c5d6f7c6204560 (patch) | |
tree | 31debd251cb5882261f3fcfe358438d802218700 /packet-rpc.c | |
parent | bb2b650c9b788b2fa4d207b0e2f1a7d575462993 (diff) | |
download | wireshark-d3512a34afde4a6a01e55e2db5c5d6f7c6204560.tar.gz wireshark-d3512a34afde4a6a01e55e2db5c5d6f7c6204560.tar.bz2 wireshark-d3512a34afde4a6a01e55e2db5c5d6f7c6204560.zip |
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
Diffstat (limited to 'packet-rpc.c')
-rw-r--r-- | packet-rpc.c | 156 |
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); } |