/* conversation.c
* Routines for building lists of packets that are part of a "conversation"
*
- * $Id: conversation.c,v 1.1 1999/10/22 07:17:28 guy Exp $
+ * $Id: conversation.c,v 1.6 2000/01/05 21:48:16 gram Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
#include <string.h>
#include <glib.h>
#include "packet.h"
+#include "conversation.h"
static GHashTable *conversation_hashtable = NULL;
static GMemChunk *conversation_key_chunk = NULL;
-static GMemChunk *conversation_val_chunk = NULL;
+static GMemChunk *conversation_chunk = NULL;
typedef struct conversation_key {
struct conversation_key *next;
address src;
address dst;
port_type ptype;
- guint16 port_src;
- guint16 port_dst;
+ guint32 port_src;
+ guint32 port_dst;
} conversation_key;
/*
*/
static conversation_key *conversation_keys;
-typedef struct conversation_val {
- struct conversation_val *next;
- guint32 index;
-} conversation_val;
-
static guint32 new_index;
static int conversation_init_count = 200;
conversation_key *v1 = (conversation_key *)v;
conversation_key *v2 = (conversation_key *)w;
- /*
- * We assume that a source and a destination address for a given
- * packet in a conversation have the same type.
- */
- if (v1->src.type != v2->src.type)
- return 0; /* different types of addresses */
-
if (v1->ptype != v2->ptype)
return 0; /* different types of port */
- if (v1->src.len == v2->src.len &&
- memcmp(v1->src.data, v2->src.data, v1->src.len) == 0) {
+ /*
+ * Are the first and second source ports the same, the first and
+ * second destination ports the same, the first and second source
+ * addresses the same, and the first and second destination
+ * addresses the same?
+ */
+ if (v1->port_src == v2->port_src &&
+ v1->port_dst == v2->port_dst &&
+ v1->src.type == v2->src.type &&
+ v1->src.len == v2->src.len &&
+ memcmp(v1->src.data, v2->src.data, v1->src.len) == 0 &&
+ v1->dst.type == v2->dst.type &&
+ v1->dst.len == v2->dst.len &&
+ memcmp(v1->dst.data, v2->dst.data, v1->dst.len) == 0) {
/*
- * The first and second source addresses are the same.
+ * Yes. It's the same conversation, and the two
+ * address/port pairs are going in the same direction.
*/
- if (v1->dst.len == v2->dst.len &&
- memcmp(v1->dst.data, v2->dst.data, v1->dst.len) == 0) {
- /*
- * The first and second destination addresses
- * are the same, so they're both going from
- * the same machine and they're both going to
- * the same machine.
- */
- if (v1->port_src == v2->port_src &&
- v1->port_dst == v2->port_dst) {
- /*
- * The first and second source ports
- * are the same, and the first and second
- * destination ports are the same, so
- * it's the same conversation, and the two
- * address/port pairs are going in the same
- * direction.
- */
- return 1;
- }
- }
- } else if (v1->src.len == v2->dst.len &&
- memcmp(v1->src.data, v2->dst.data, v1->src.len) == 0) {
+ return 1;
+ }
+
+ /*
+ * Is the first source port the same as the second destination
+ * port, the first destination port the same as the first
+ * source port, the first source address the same as the second
+ * destination address, and the first destination address the
+ * same as the second source address?
+ */
+ if (v1->port_src == v2->port_dst &&
+ v1->port_dst == v2->port_src &&
+ v1->src.type == v2->dst.type &&
+ v1->src.len == v2->dst.len &&
+ memcmp(v1->src.data, v2->dst.data, v1->src.len) == 0 &&
+ v1->dst.type == v2->src.type &&
+ v1->dst.len == v2->src.len &&
+ memcmp(v1->dst.data, v2->src.data, v1->dst.len) == 0) {
/*
- * The first source address is the same as the second
- * destination address.
+ * Yes. It's the same conversation, and the two
+ * address/port pairs are going in opposite directions.
*/
- if (v1->dst.len == v2->src.len &&
- memcmp(v1->dst.data, v2->src.data, v1->dst.len) == 0) {
- /*
- * The first destination address is the same as
- * the second source address, so they're going
- * between the same machines, but in opposite
- * directions.
- */
- if (v1->port_src == v2->port_dst &&
- v1->port_dst == v2->port_src) {
- /*
- * The first source port is the same as
- * the second destination port, and the
- * first destination port is the same as
- * the second source port, so it's
- * the same conversation, and the two
- * address/port pairs are going in
- * opposite directions.
- */
- return 1;
- }
- }
+ return 1;
}
/*
g_free((gpointer)key->src.data);
g_free((gpointer)key->dst.data);
}
+ conversation_keys = NULL;
if (conversation_hashtable != NULL)
g_hash_table_destroy(conversation_hashtable);
if (conversation_key_chunk != NULL)
g_mem_chunk_destroy(conversation_key_chunk);
- if (conversation_val_chunk != NULL)
- g_mem_chunk_destroy(conversation_val_chunk);
+ if (conversation_chunk != NULL)
+ g_mem_chunk_destroy(conversation_chunk);
conversation_hashtable = g_hash_table_new(conversation_hash,
conversation_equal);
sizeof(conversation_key),
conversation_init_count * sizeof(struct conversation_key),
G_ALLOC_AND_FREE);
- conversation_val_chunk = g_mem_chunk_new("conversation_val_chunk",
- sizeof(conversation_val),
- conversation_init_count * sizeof(struct conversation_val),
+ conversation_chunk = g_mem_chunk_new("conversation_chunk",
+ sizeof(conversation_t),
+ conversation_init_count * sizeof(conversation_t),
G_ALLOC_AND_FREE);
/*
}
/*
- * Given source and destination addresses and ports for a packet, add
- * it to the conversation containing packets between those address/port
- * pairs, creating a new conversation if none exists between them.
- *
- * Returns an index to use to refer to the conversation.
+ * Given source and destination addresses and ports for a packet,
+ * create a new conversation to contain packets between those address/port
+ * pairs.
+ */
+conversation_t *
+conversation_new(address *src, address *dst, port_type ptype,
+ guint32 src_port, guint32 dst_port, void *data)
+{
+ conversation_t *conversation;
+ conversation_key *new_key;
+
+ new_key = g_mem_chunk_alloc(conversation_key_chunk);
+ new_key->next = conversation_keys;
+ conversation_keys = new_key;
+ copy_address(&new_key->src, src);
+ copy_address(&new_key->dst, dst);
+ new_key->ptype = ptype;
+ new_key->port_src = src_port;
+ new_key->port_dst = dst_port;
+
+ conversation = g_mem_chunk_alloc(conversation_chunk);
+ conversation->index = new_index;
+ conversation->data = data;
+ new_index++;
+
+ g_hash_table_insert(conversation_hashtable, new_key, conversation);
+ return conversation;
+}
+
+/*
+ * Given source and destination addresses and ports for a packet,
+ * search for a conversation containing packets between those address/port
+ * pairs. Returns NULL if not found.
*/
-guint32
-add_to_conversation(address *src, address *dst, port_type ptype,
- guint16 src_port, guint16 dst_port)
+conversation_t *
+find_conversation(address *src, address *dst, port_type ptype,
+ guint32 src_port, guint32 dst_port)
{
- conversation_val *conversation;
- conversation_key key, *new_key;
+ conversation_key key;
/*
* We don't make a copy of the address data, we just copy the
key.ptype = ptype;
key.port_src = src_port;
key.port_dst = dst_port;
- conversation =
- (conversation_val *)g_hash_table_lookup(conversation_hashtable,
- &key);
- if (conversation == NULL) {
- /*
- * No such conversation yet.
- * Allocate a new one.
- * Here, we *do* have to copy the address data.
- */
- new_key = g_mem_chunk_alloc(conversation_key_chunk);
- new_key->next = conversation_keys;
- conversation_keys = new_key;
- copy_address(&new_key->src, src);
- copy_address(&new_key->dst, dst);
- new_key->ptype = ptype;
- new_key->port_src = src_port;
- new_key->port_dst = dst_port;
-
- conversation = g_mem_chunk_alloc(conversation_val_chunk);
- conversation->index = new_index;
- new_index++;
-
- g_hash_table_insert(conversation_hashtable, new_key,
- conversation);
- }
- return conversation->index;
+ return g_hash_table_lookup(conversation_hashtable, &key);
}