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):