Ethereal-dev: [ethereal-dev] ICQ dissector
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Kojak <kojak@xxxxxxxxxx>
Date: Fri, 24 Dec 1999 15:57:01 +0100
Hi
I added the routines to dynamically set the correct TCP portnumbers to the
icq-tcp dissector. However, the current implementation doesn't quite work.
The display filter is compiled ok, but the dissector is not called. Currently
I don't have a clue why.
Here's the code at least, so others can comment on the chosen method, which
boils down to: "keep a list of portnumbers, if one is added, generate a
new filter string, recompile the filter and install".
Grtz
Kojak
Index: packet-icq.c
===================================================================
RCS file: /cvsroot/ethereal/packet-icq.c,v
retrieving revision 1.9
diff -u -r1.9 packet-icq.c
--- packet-icq.c 1999/12/05 22:59:55 1.9
+++ packet-icq.c 1999/12/24 14:49:09
@@ -67,6 +67,10 @@
#include "packet.h"
#include "resolv.h"
+#include "globals.h"
+#include "plugins.h"
+#include "dfilter.h"
+#include "ui_util.h"
static int proto_icq = -1;
static int hf_icq_uin =-1;
@@ -84,11 +88,20 @@
enum { ICQ5_client, ICQ5_server};
+static gchar Dissect_TCP_ICQ_Version[]="tcp dissect 0.0.1";
+static gchar Dissect_TCP_ICQ_Name[]="tcp dissect 0.0.1";
+static GList* watchList = NULL;
+
void dissect_icqv5(const u_char *pd,
int offset,
frame_data *fd,
proto_tree *tree);
+void dissect_icq_chat(const u_char *pd,
+ int offset,
+ frame_data *fd,
+ proto_tree *tree);
+
static void
dissect_icqv5Server(const u_char *pd,
int offset,
@@ -386,7 +399,118 @@
0x3B, 0x4D, 0x46, 0x68, 0x63, 0x39, 0x50, 0x5F, 0x5F, 0x3F, 0x6F, 0x67, 0x53, 0x41, 0x25, 0x41,
0x3C, 0x51, 0x54, 0x3D, 0x5E, 0x54, 0x5D, 0x4E, 0x4C, 0x39, 0x50, 0x5F, 0x5F, 0x5F, 0x3F, 0x6F,
0x47, 0x43, 0x69, 0x48, 0x33, 0x51, 0x54, 0x5D, 0x6E, 0x3C, 0x31, 0x64, 0x35, 0x5A, 0x00, 0x00 };
-
+
+static void
+generateFilter(GList* list)
+{
+ int n = 0;
+ int i = 0;
+ int res = 0;
+ int size = 0;
+ char* buf = NULL;
+ GList* iptr = NULL;
+ n = g_list_length(list);
+ size = n * sizeof("tcp.port==xxxxx ||");
+ buf = g_malloc(size);
+ i = 0;
+ for ( iptr=g_list_first(list);
+ iptr!=NULL;
+ iptr=g_list_next(iptr)) {
+ fprintf(stderr,"ICQ: Port = %d\n", GPOINTER_TO_INT(iptr->data));
+ if (i==0) {
+ res = snprintf(buf+i,size - i,"tcp.port==%d", GPOINTER_TO_INT(iptr->data));
+ } else {
+ res = snprintf(buf+i,size - i,"|| tcp.port==%d", GPOINTER_TO_INT(iptr->data));
+ }
+ i += res;
+ }
+ fprintf(stderr,"ICQ: Setting filter %d ports \"%s\"\n", n, buf);
+ if (n>0) {
+ dfilter* df = NULL;
+ if (dfilter_compile(buf, &df)==0) {
+ plugin_replace_filter(Dissect_TCP_ICQ_Name,
+ Dissect_TCP_ICQ_Version,
+ buf,
+ df);
+ enable_plugin(Dissect_TCP_ICQ_Name,
+ Dissect_TCP_ICQ_Version);
+ } else {
+ simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
+ }
+ } else {
+ disable_plugin(Dissect_TCP_ICQ_Name,
+ Dissect_TCP_ICQ_Version);
+ }
+ g_free(buf);
+}
+
+/*
+ * Adds a new tcp port to the list to be watched. This is for the time
+ * being, until there is a more elegant way to do this
+ */
+static GList*
+addWatchTCPPort(GList* list, guint16 port)
+{
+ fprintf(stderr, "ICQ: watchList[%d]\n", g_list_length(list));
+ if (g_list_index(list, GINT_TO_POINTER(port))==-1) {
+ list = g_list_append(list, GINT_TO_POINTER((guint32)port));
+ fprintf(stderr, "ICQ: watchList[%d]\n", g_list_length(list));
+ generateFilter(list);
+ }
+ return list;
+}
+
+/*
+ * delete the named port from the watchlist
+ */
+static GList*
+deleteWatchTCPPort(GList* list, guint16 port)
+{
+ list = g_list_remove(list, GINT_TO_POINTER((guint32)port));
+ generateFilter(list);
+ return list;
+}
+
+/*
+ * Initialize the structure, and set the filters to a proper value
+ */
+static int
+initWatchList(GList* list,
+ void (*dissector) (const u_char *, int, frame_data *, proto_tree *))
+{
+ /* list is not used, but inserted to be able to maybe change the
+ * implementation later on.
+ */
+ int res;
+ res = add_plugin(NULL, /* This is not from a dynamic thing */
+ Dissect_TCP_ICQ_Name,
+ Dissect_TCP_ICQ_Version,
+ "tcp",
+ NULL, /* Do not add a filter right now */
+ NULL, /* Can you pass a NULL compiled filter */
+ dissector);
+ disable_plugin(Dissect_TCP_ICQ_Name, Dissect_TCP_ICQ_Version);
+ return (res);
+}
+
+/*
+ * Delete all the ports from the filter, and destroy the
+ * list itself.
+ */
+static void
+deleteWatchList(GList* list)
+{
+ plugin_replace_filter(Dissect_TCP_ICQ_Name,
+ Dissect_TCP_ICQ_Version,
+ NULL,
+ NULL); /* Legal to pass non-compiled string? */
+ disable_plugin(Dissect_TCP_ICQ_Name, Dissect_TCP_ICQ_Version);
+ g_list_free(list);
+}
+
+/*
+ * Find a cmdcode in the map between a code and its description.
+ */
static char*
findcmd(cmdcode* c, int num)
{
@@ -1197,6 +1321,7 @@
}
if (left>=8) {
port = pletohl(pd + CMD_LOGIN_PORT);
+ watchList = addWatchTCPPort(watchList, port);
}
if (left>=10) {
passwdLen = pletohs(pd + CMD_LOGIN_PASSLEN);
@@ -1405,8 +1530,10 @@
if (size >= SRV_USER_ONL_IP + 4)
ipAddrp = &pd[SRV_USER_ONL_IP];
- if (size >= SRV_USER_ONL_PORT + 4)
+ if (size >= SRV_USER_ONL_PORT + 4) {
port = pletohl(pd + SRV_USER_ONL_PORT);
+ watchList = addWatchTCPPort(watchList, port);
+ }
if (size >= SRV_USER_ONL_REALIP + 4)
realipAddrp = &pd[SRV_USER_ONL_REALIP];
@@ -1545,6 +1672,7 @@
{
#if 0
proto_tree* subtree = NULL;
+ proto_tree* sstree = NULL;
#endif
proto_tree* sstree = NULL;
proto_item* ti = NULL;
@@ -1897,6 +2025,11 @@
guint16 tcpVer;
int left = size;
+ if (left >= SRV_RAND_USER_PORT + sizeof(guint32)) {
+ fprintf("ICQ: Adding a port (tree = %p)\n", tree);
+ port = pletohs(pd + SRV_RAND_USER_PORT);
+ watchList = addWatchTCPPort(watchList, port);
+ }
if (tree) {
ti = proto_tree_add_item_format(tree,
hf_icq_cmd,
@@ -1927,6 +2060,7 @@
if (left<sizeof(guint32))
return;
port = pletohs(pd + SRV_RAND_USER_PORT);
+ watchList = addWatchTCPPort(watchList, port);
proto_tree_add_text(subtree,
offset + SRV_RAND_USER_UIN,
sizeof(guint32),
@@ -1988,7 +2122,7 @@
guint16 seqnum1 = 0 , seqnum2 = 0;
guint32 uin = -1, sessionid = -1;
guint32 key = -1;
- guint16 pktsize = -1; /* The size of the ICQ content */
+ guint16 pktsize = -1; /* The size of the ICQ content */
u_char decr_pd[1600]; /* Decrypted content, size should be dynamic */
pktsize = fd->pkt_len - offset;
@@ -2059,80 +2193,82 @@
offset + ICQ5_CL_SEQNUM1,
2,
"Seqnum2: 0x%04x", seqnum2);
- switch(cmd) {
- case CMD_ACK:
- icqv5_cmd_ack(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_SEND_MSG:
- case CMD_MSG_TO_NEW_USER:
- icqv5_cmd_send_msg(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE,
- cmd);
- break;
- case CMD_RAND_SEARCH:
- icqv5_cmd_rand_search(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
- break;
+ }
+ switch(cmd) {
+ case CMD_ACK:
+ icqv5_cmd_ack(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_SEND_MSG:
+ case CMD_MSG_TO_NEW_USER:
+ icqv5_cmd_send_msg(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE,
+ cmd);
+ break;
+ case CMD_RAND_SEARCH:
+ icqv5_cmd_rand_search(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
case CMD_LOGIN:
icqv5_cmd_login(icq_tree,
decr_pd + ICQ5_CL_HDRSIZE,
offset + ICQ5_CL_HDRSIZE,
pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_SEND_TEXT_CODE:
- icqv5_cmd_send_text_code(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_STATUS_CHANGE:
- icqv5_cmd_status_change(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
break;
- case CMD_ACK_MESSAGES:
- icqv5_cmd_ack_messages(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_KEEP_ALIVE:
- icqv5_cmd_keep_alive(icq_tree,
+ case CMD_SEND_TEXT_CODE:
+ icqv5_cmd_send_text_code(icq_tree,
decr_pd + ICQ5_CL_HDRSIZE,
offset + ICQ5_CL_HDRSIZE,
pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_ADD_TO_LIST:
- icqv5_cmd_add_to_list(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_CONTACT_LIST:
- icqv5_cmd_contact_list(icq_tree,
- decr_pd + ICQ5_CL_HDRSIZE,
- offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE);
- break;
- case CMD_META_USER:
- case CMD_REG_NEW_USER:
- case CMD_QUERY_SERVERS:
- case CMD_QUERY_ADDONS:
- icqv5_cmd_no_params(icq_tree,
+ break;
+ case CMD_STATUS_CHANGE:
+ icqv5_cmd_status_change(icq_tree,
decr_pd + ICQ5_CL_HDRSIZE,
offset + ICQ5_CL_HDRSIZE,
- pktsize - ICQ5_CL_HDRSIZE,
- cmd);
- break;
- default:
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_ACK_MESSAGES:
+ icqv5_cmd_ack_messages(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_KEEP_ALIVE:
+ icqv5_cmd_keep_alive(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_ADD_TO_LIST:
+ icqv5_cmd_add_to_list(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_CONTACT_LIST:
+ icqv5_cmd_contact_list(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE);
+ break;
+ case CMD_META_USER:
+ case CMD_REG_NEW_USER:
+ case CMD_QUERY_SERVERS:
+ case CMD_QUERY_ADDONS:
+ icqv5_cmd_no_params(icq_tree,
+ decr_pd + ICQ5_CL_HDRSIZE,
+ offset + ICQ5_CL_HDRSIZE,
+ pktsize - ICQ5_CL_HDRSIZE,
+ cmd);
+ break;
+ default:
+ if (tree)
proto_tree_add_item_format(icq_tree,
hf_icq_cmd,
offset+ICQ5_CL_CMD,
@@ -2140,9 +2276,10 @@
cmd,
"Command: %d (%s)",
cmd, findClientCmd(cmd));
- fprintf(stderr,"Missing: %s\n", findClientCmd(cmd));
- break;
- }
+ fprintf(stderr,"Missing: %s\n", findClientCmd(cmd));
+ break;
+ }
+ if (tree) {
ti = proto_tree_add_text(icq_tree,
offset,
pktsize,
@@ -2150,7 +2287,6 @@
icq_decode_tree = proto_item_add_subtree(ti,
ett_icq_decode);
proto_tree_add_hexdump(icq_decode_tree, offset, decr_pd, pktsize);
-
}
}
@@ -2238,87 +2374,89 @@
checkcode,
"Checkcode: 0x%08x",
checkcode);
- switch (cmd) {
- case SRV_RAND_USER:
- icqv5_srv_rand_user(icq_tree,
- decr_pd + ICQ5_SRV_HDRSIZE,
- offset + ICQ5_SRV_HDRSIZE,
- pktsize - ICQ5_SRV_HDRSIZE);
- break;
- case SRV_SYS_DELIVERED_MESS:
- /* The message structures are all the same. Why not run
- * the same routine? */
- icqv5_cmd_send_msg(icq_tree,
- decr_pd + ICQ5_SRV_HDRSIZE,
- offset + ICQ5_SRV_HDRSIZE,
- pktsize - ICQ5_SRV_HDRSIZE,
- cmd);
- break;
- case SRV_USER_ONLINE:
- icqv5_srv_user_online(icq_tree,
- decr_pd + ICQ5_SRV_HDRSIZE,
- offset + ICQ5_SRV_HDRSIZE,
- pktsize - ICQ5_SRV_HDRSIZE);
- break;
- case SRV_USER_OFFLINE:
- icqv5_srv_user_offline(icq_tree,
- decr_pd + ICQ5_SRV_HDRSIZE,
- offset + ICQ5_SRV_HDRSIZE,
- pktsize - ICQ5_SRV_HDRSIZE);
- break;
- case SRV_LOGIN_REPLY:
- icqv5_srv_login_reply(icq_tree,
+ }
+ switch (cmd) {
+ case SRV_RAND_USER:
+ icqv5_srv_rand_user(icq_tree,
+ decr_pd + ICQ5_SRV_HDRSIZE,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_SYS_DELIVERED_MESS:
+ /* The message structures are all the same. Why not run
+ * the same routine? */
+ icqv5_cmd_send_msg(icq_tree,
+ decr_pd + ICQ5_SRV_HDRSIZE,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE,
+ cmd);
+ break;
+ case SRV_USER_ONLINE:
+ icqv5_srv_user_online(icq_tree,
+ decr_pd + ICQ5_SRV_HDRSIZE,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_USER_OFFLINE:
+ icqv5_srv_user_offline(icq_tree,
decr_pd + ICQ5_SRV_HDRSIZE,
offset + ICQ5_SRV_HDRSIZE,
pktsize - ICQ5_SRV_HDRSIZE);
- break;
- case SRV_META_USER:
- icqv5_srv_meta_user(icq_tree,
+ break;
+ case SRV_LOGIN_REPLY:
+ icqv5_srv_login_reply(icq_tree,
+ decr_pd + ICQ5_SRV_HDRSIZE,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_META_USER:
+ icqv5_srv_meta_user(icq_tree,
+ decr_pd + ICQ5_SRV_HDRSIZE,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE);
+ break;
+ case SRV_RECV_MESSAGE:
+ icqv5_srv_recv_message(icq_tree,
decr_pd + ICQ5_SRV_HDRSIZE,
offset + ICQ5_SRV_HDRSIZE,
pktsize - ICQ5_SRV_HDRSIZE);
- break;
- case SRV_RECV_MESSAGE:
- icqv5_srv_recv_message(icq_tree,
- decr_pd + ICQ5_SRV_HDRSIZE,
- offset + ICQ5_SRV_HDRSIZE,
- pktsize - ICQ5_SRV_HDRSIZE);
- break;
- case SRV_MULTI:
- icqv5_srv_multi(icq_tree,
+ break;
+ case SRV_MULTI:
+ icqv5_srv_multi(icq_tree,
+ decr_pd + ICQ5_SRV_HDRSIZE,
+ offset + ICQ5_SRV_HDRSIZE,
+ pktsize - ICQ5_SRV_HDRSIZE,
+ fd);
+ break;
+ case SRV_ACK:
+ case SRV_GO_AWAY:
+ case SRV_NEW_UIN:
+ case SRV_BAD_PASS:
+ case SRV_UPDATE_SUCCESS:
+ icqv5_srv_no_params(icq_tree,
decr_pd + ICQ5_SRV_HDRSIZE,
offset + ICQ5_SRV_HDRSIZE,
pktsize - ICQ5_SRV_HDRSIZE,
- fd);
- break;
- case SRV_ACK:
- case SRV_GO_AWAY:
- case SRV_NEW_UIN:
- case SRV_BAD_PASS:
- case SRV_UPDATE_SUCCESS:
- icqv5_srv_no_params(icq_tree,
- decr_pd + ICQ5_SRV_HDRSIZE,
- offset + ICQ5_SRV_HDRSIZE,
- pktsize - ICQ5_SRV_HDRSIZE,
- cmd);
- break;
- default:
- proto_tree_add_item_format(icq_tree,
- hf_icq_cmd,
- offset + ICQ5_SRV_CMD,
- 2,
- cmd,
- "Command: %d (%s)",
- cmd, findServerCmd(cmd));
- fprintf(stderr,"Missing: %s\n", findServerCmd(cmd));
- break;
- }
-
+ cmd);
+ break;
+ default:
+ proto_tree_add_item_format(icq_tree,
+ hf_icq_cmd,
+ offset + ICQ5_SRV_CMD,
+ 2,
+ cmd,
+ "Command: %d (%s)",
+ cmd, findServerCmd(cmd));
+ fprintf(stderr,"Missing: %s\n", findServerCmd(cmd));
+ break;
+ }
+
+ if (tree) {
ti = proto_tree_add_text(icq_tree,
offset,
pktsize,
"Decoded packet");
- icq_decode_tree = proto_item_add_subtree(ti,
+ icq_decode_tree = proto_item_add_subtree(ti,
ett_icq_decode);
proto_tree_add_hexdump(icq_decode_tree, offset, decr_pd, pktsize);
}
@@ -2342,6 +2480,16 @@
}
}
+void dissect_icq_chat(const u_char *pd,
+ int offset,
+ frame_data *fd,
+ proto_tree *tree)
+{
+ fprintf(stderr, "Dissect ICQ Chat\n");
+ if (check_col(fd, COL_PROTOCOL))
+ col_add_str(fd, COL_PROTOCOL, "ICQ chat");
+}
+
void dissect_icq(const u_char *pd,
int offset,
frame_data *fd,
@@ -2394,4 +2542,19 @@
proto_register_field_array(proto_icq, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+}
+
+/*
+ * This routine is called when a new file is opened, or when a new
+ * pass is made through the capture.
+ */
+void
+icq_init_protocol()
+{
+ /* Clear all filters available
+ * so the dissector can start with a clean repsheat.
+ */
+ deleteWatchList(watchList);
+ watchList = NULL; /* It has been removed by deleteWatchList */
+ initWatchList(watchList, dissect_icq_chat);
}
- Prev by Date: [ethereal-dev] Re: Problems in the "Ethereal"
- Next by Date: [ethereal-dev] configuring cvs version of ethereal
- Previous by thread: [ethereal-dev] Re: Problems in the "Ethereal"
- Next by thread: [ethereal-dev] configuring cvs version of ethereal
- Index(es):





