Ethereal-dev: [ethereal-dev] Packet-icq update
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Kojak <kojak@xxxxxxxxxx>
Date: Mon, 25 Oct 1999 21:32:28 +0200
Hi, A patch to the ICQ code. It's far from finished, but the login packets are displayed ok, as are the text messages. Kojak Index: packet-icq.c =================================================================== RCS file: /cvsroot/ethereal/packet-icq.c,v retrieving revision 1.1 diff -r1.1 packet-icq.c 46a47,50 > #ifdef HAVE_ARPA_INET_H > #include <arpa/inet.h> > #endif > 50a55 > #include <string.h> 123a129,189 > #define MSG_TEXT 0x0001 > #define MSG_URL 0x0004 > #define MSG_AUTH_REQ 0x0006 > #define MSG_AUTH 0x0008 > #define MSG_USER_ADDED 0x000c > #define MSG_CONTACTS 0x0013 > > #define STATUS_ONLINE 0x00000000 > #define STATUS_AWAY 0x00000001 > #define STATUS_DND 0x00000013 > #define STATUS_INVISIBLE 0x00000100 > #define STATUS_OCCUPIED 0x00000010 > #define STATUS_NA 0x00000004 > #define STATUS_CHAT 0x00000020 > > /* Offsets for all packets measured from the start of the payload; i.e. > * with the ICQ header removed > */ > #define CMD_ACK 0x000a > #define CMD_ACK_RANDOM 0x0000 > > #define CMD_SEND_MSG 0x010E > #define CMD_SEND_MSG_RECV_UIN 0x0000 > #define CMD_SEND_MSG_MSG_TYPE 0x0004 > #define CMD_SEND_MSG_MSG_LEN 0x0006 > #define CMD_SEND_MSG_MSG_TEXT 0x0008 > /* The rest of the packet should be a null-term string */ > > #define CMD_LOGIN 0x03E8 > #define CMD_LOGIN_TIME 0x0000 > #define CMD_LOGIN_PORT 0x0004 > #define CMD_LOGIN_PASSLEN 0x0008 > #define CMD_LOGIN_PASSWD 0x000A > /* The password is variable length; so when we've decoded the passwd, > * the structure starts counting at 0 again. > */ > #define CMD_LOGIN_IP 0x0004 > #define CMD_LOGIN_STATUS 0x0009 > > > cmdcode msgTypeCode[] = { > { "MSG_TEXT", MSG_TEXT }, > { "MSG_URL", MSG_URL }, > { "MSG_AUTH_REQ", MSG_AUTH_REQ }, > { "MSG_AUTH", MSG_AUTH }, > { "MSG_USER_ADDED", MSG_USER_ADDED}, > { "MSG_CONTACTS", MSG_CONTACTS}, > { NULL, 0} > }; > > cmdcode statusCode[] = { > { "ONLINE", STATUS_ONLINE }, > { "AWAY", STATUS_AWAY }, > { "DND", STATUS_DND }, > { "INVISIBLE", STATUS_INVISIBLE }, > { "OCCUPIED", STATUS_OCCUPIED }, > { "NA", STATUS_NA }, > { "Free for Chat", STATUS_CHAT }, > { NULL, 0} > }; > 125,127c191,193 < { "CMD_ACK", 10 }, < { "CMD_SEND_MESSAGE", 270 }, < { "CMD_LOGIN", 1000 }, --- > { "CMD_ACK", CMD_ACK }, > { "CMD_SEND_MESSAGE", CMD_SEND_MSG }, > { "CMD_LOGIN", CMD_LOGIN }, 160,178d225 < typedef struct { < u_int32_t random; < } cl_cmd_ack; < < typedef struct _cl_cmd_send_msg { < #define MSG_TEXT 0x0100 < #define MSG_URL 0x0400 < #define MSG_AUTH_REQ 0x0600 < #define MSG_AUTH 0x0800 < #define MSG_USER_ADDED 0x0c00 < #define MSG_CONTACTS 0x1300 < u_int32_t receiverUIN; < u_int16_t msgType; < u_int16_t msgLen; < /* < * Followed by char[msgLen] < */ < } cl_cmd_send_msg; < 206c253 < while (p->code != 0) { --- > while (p->descr != NULL) { 216c263,287 < void --- > static char* > findMsgType(int num) > { > return findcmd(msgTypeCode, num); > } > > static char* > findClientCmd(int num) > { > return findcmd(clientCmdCode, num); > } > > static char* > findServerCmd(int num) > { > return findcmd(serverCmdCode, num); > } > > static char* > findStatus(int num) > { > return findcmd(statusCode, num); > } > > static void 352a424,751 > * Find first occurrence of ch in buf > * Buf is max size big. > */ > static char* > strnchr(const u_char* buf, u_char ch, int size) > { > int i; > u_char* p = (u_char*) buf; > for (i=0;(*p) && (*p!=ch) && (i<size); p++, i++) > ; > if ((*p == '\0') || (i>=size)) > return NULL; > return p; > } > > static void > icqv5_cmd_ack(proto_tree* tree,/* Tree to put the data in */ > const u_char* pd, /* Packet content */ > int offset, /* Offset from the start of the packet to the content */ > int size) /* Number of chars left to do */ > { > u_int32_t random = pletohl(pd + CMD_ACK_RANDOM); > proto_tree* subtree; > proto_item* ti; > > if (tree){ > ti = proto_tree_add_item_format(tree, > hf_icq_cmd, > offset, > 4, > CMD_ACK, > "%s : %d", > findClientCmd(CMD_ACK), > CMD_ACK); > subtree = proto_item_add_subtree(ti, ETT_ICQ_SUBTREE); > proto_tree_add_text(subtree, > offset + CMD_ACK_RANDOM, > 4, > "Random: 0x%08lx", random); > } > } > > static void > icqv5_cmd_send_msg(proto_tree* tree, > const u_char* pd, > int offset, > int size) > { > proto_tree* subtree; > proto_item* ti; > u_int32_t receiverUIN = 0xffffffff; > u_int16_t msgType = 0xffff; > u_int16_t msgLen = 0xffff; > u_char* msgText = NULL; > int left = size; /* left chars to do */ > int i,n,j; > static char* auth_req_field_descr[] = { > "Nickname", > "First name", > "Last name", > "Email address", > "Reason"}; > > if (left >= 4) { > receiverUIN = pletohl(pd + CMD_SEND_MSG_RECV_UIN); > left -= 4; > } > if (left >= 2) { > msgType = pletohs(pd + CMD_SEND_MSG_MSG_TYPE); > left -= 2; > } > if (left >= 2) { > msgLen = pletohs(pd + CMD_SEND_MSG_MSG_LEN); > left -= 2; > } > if (tree) { > ti = proto_tree_add_item_format(tree, > hf_icq_cmd, > offset, > size, > CMD_SEND_MSG, > "Body"); > subtree = proto_item_add_subtree(ti, ETT_ICQ_SUBTREE); > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_RECV_UIN, > 4, > "Receiver UIN: %ld", receiverUIN); > ti = proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TYPE, > 2, > "Type: %d (%s)", msgType, findMsgType(msgType)); > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_LEN, > 2, > "Length: %d", msgLen); > > /* It's silly to do anything if there's nothing left */ > if (left==0) > return; > if (msgLen == 0) > return; > /* Create a subtree for every message type */ > switch(msgType) { > case 0xffff: /* Field unknown */ > break; > case MSG_TEXT: > msgText = g_malloc(left + 1); > strncpy(msgText, pd + CMD_SEND_MSG_MSG_TEXT, left); > msgText[left] = '\0'; > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT, > left, > "Msg: %s", msgText); > g_free(msgText); > break; > case MSG_URL: > /* Two parts, a description and the URL. Separeted by FE */ > for (i=0;i<left;i++) { > if (pd[CMD_SEND_MSG_MSG_TEXT + i] == 0xfe) > break; > } > msgText = g_malloc(i + 1); > strncpy(msgText, pd + CMD_SEND_MSG_MSG_TEXT, i); > if (i==left) > msgText[i] = '\0'; > else > msgText[i-1] = '\0'; > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT, > i, > "Description: %s", msgText); > if (i==left) > break; > msgText = g_realloc(msgText, left - i); > strncpy(msgText, pd + CMD_SEND_MSG_MSG_TEXT + i + 1, left - i - 1); > msgText[left - i] = '\0'; > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT, > i, > "URL: %s", msgText); > g_free(msgText); > break; > case MSG_AUTH_REQ: > /* Five parts, separated by FE */ > i = 0; > j = 0; > msgText = NULL; > for (n = 0; n < 5; n++) { > for (; > (i<left) && (pd[CMD_SEND_MSG_MSG_TEXT+i]!=0xfe); > i++) > ; > msgText = g_realloc(msgText, i-j); > strncpy(msgText, pd + CMD_SEND_MSG_MSG_TEXT + j, i - j - 1); > msgText[i-j-1] = '\0'; > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT + j, > i - j - 1, > "%s: %s", auth_req_field_descr[n], msgText); > j = ++i; > } > if (msgText != NULL) > g_free(msgText); > break; > case MSG_USER_ADDED: > /* Create a new subtree */ > subtree = proto_item_add_subtree(ti, ETT_ICQ_SUBTREE); > /* Four parts, separated by FE */ > i = 0; > j = 0; > /* This is necessary, because g_realloc does not behave like > * g_malloc if the first parameter == NULL */ > msgText = g_malloc(64); > for (n = 0; n < 4; n++) { > for (; > (i<left) && (pd[CMD_SEND_MSG_MSG_TEXT+i]!=0xfe); > i++) > ; > msgText = g_realloc(msgText, i-j+1); > strncpy(msgText, pd + CMD_SEND_MSG_MSG_TEXT + j, i - j); > msgText[i-j] = '\0'; > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT + j, > i - j, > "%s: %s", auth_req_field_descr[n], msgText); > j = ++i; > } > if (msgText != NULL) > g_free(msgText); > break; > case MSG_CONTACTS: > { > u_char* p = (u_char*) &pd[CMD_SEND_MSG_MSG_TEXT]; > u_char* pprev = p; > int sz = 0; /* Size of the current element */ > int n = 0; /* The nth element */ > int done = 0; /* Number of chars processed */ > u_char* msgText2 = NULL; > msgText = NULL; > /* Create a new subtree */ > subtree = proto_item_add_subtree(ti, ETT_ICQ_SUBTREE); > while (p!=NULL) { > p = strnchr(pprev, 0xfe, left); > > if (p!=NULL) > sz = (int)(p - pprev); > else > sz = left; > msgText = g_realloc(msgText, sz+1); > strncpy(msgText, pprev, sz); > msgText[sz] = '\0'; > > if (n == 0) { > /* The first element is the number of Nick/UIN pairs follow */ > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT + done, > sz, > "Number of pairs: %s", msgText); > n++; > } else if (p!=NULL) { > int svsz = sz; > left -= (sz+1); > pprev = p + 1; > p = strnchr(pprev, 0xfe, left); > if (p!=NULL) > sz = (int)(p - pprev); > else > sz = left; > msgText2 = g_malloc(sz+1); > strncpy(msgText2, pprev, sz); > msgText2[sz] = '\0'; > > proto_tree_add_text(subtree, > offset + CMD_SEND_MSG_MSG_TEXT + done, > sz + svsz + 2, > "%s:%s", msgText, msgText2); > n+=2; > g_free(msgText2); > } > > left -= (sz+1); > pprev = p+1; > } > if (msgText != NULL) > g_free(msgText); > break; > }} > } > } > > static void > icqv5_cmd_login(proto_tree* tree, > const u_char* pd, > int offset, > int size) > { > proto_item* ti; > proto_tree* subtree; > u_int32_t theTime = -1; > u_int32_t port = -1; > u_int32_t passwdLen = -1; > char* password = NULL; > u_int32_t ipAddr = INADDR_ANY; > u_int32_t status = -1; > u_int32_t left = size; > > if (left>=4) { > theTime = pletohl(pd + CMD_LOGIN_TIME); > } > if (left>=8) { > port = pletohl(pd + CMD_LOGIN_PORT); > } > if (left>=10) { > passwdLen = pletohs(pd + CMD_LOGIN_PASSLEN); > } > if (left>=10+passwdLen) { > password = g_malloc(passwdLen); > strncpy(password, pd + CMD_LOGIN_PASSWD, passwdLen); > } > > if (left>=10+passwdLen+CMD_LOGIN_IP+4) { > ipAddr = pletohs(pd + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_IP); > } > if (left>=10+passwdLen+CMD_LOGIN_STATUS+4) { > status = pletohs(pd + CMD_LOGIN_PASSWD + passwdLen + CMD_LOGIN_STATUS); > } > if (tree) { > ti = proto_tree_add_item_format(tree, > hf_icq_cmd, > offset, > size, > CMD_SEND_MSG, > "Body"); > subtree = proto_item_add_subtree(ti, ETT_ICQ_SUBTREE); > if (theTime!=-1) > proto_tree_add_text(subtree, > offset + CMD_LOGIN_TIME, > 4, > "Time: %d = %s", theTime, ctime(&theTime)); > if (port!=-1) > proto_tree_add_text(subtree, > offset + CMD_LOGIN_PORT, > 4, > "Port: %d", port); > if ((passwdLen!=-1) && (password!=NULL)) > proto_tree_add_text(subtree, > offset + CMD_LOGIN_PASSLEN, > 2 + passwdLen, > "Passwd: %s", password); > /* > * The following is quick and dirty. Should use inet_ntop > */ > if (ipAddr!=INADDR_ANY) > proto_tree_add_text(subtree, > offset + CMD_LOGIN_PASSWD + CMD_LOGIN_IP, > 4, > "IP: %s", inet_ntoa(ipAddr)); > if (status!=-1) > proto_tree_add_text(subtree, > offset + CMD_LOGIN_PASSWD + CMD_LOGIN_IP, > 4, > "Status: %s", findStatus(status)); > } > if (password!=NULL) > g_free(password); > } > > /* 361a761 > proto_tree *icq_header_tree = NULL; 388a789,791 > > if (check_col(fd, COL_INFO)) > col_add_fstr(fd, COL_INFO, "ICQv5 %s", findClientCmd(cmd)); 396c799,801 < "ICQv5 Client: len %d", pktsize); --- > "ICQv5 %s (len %d)", > findClientCmd(cmd), > pktsize); 398,404c803,809 < proto_tree_add_item_format(icq_tree, < hf_icq_cmd, < offset+ICQ5_CL_CMD, < 2, < cmd, < "Command: %d (%s)", cmd, findcmd(clientCmdCode, cmd)); < proto_tree_add_item_format(icq_tree, --- > ti = proto_tree_add_text(icq_tree, > offset, > ICQ5_CL_HDRSIZE, > "Header"); > icq_header_tree = proto_item_add_subtree(ti, ETT_ICQ_SUBTREE); > > proto_tree_add_item_format(icq_header_tree, 411c816 < proto_tree_add_item_format(icq_tree, --- > proto_tree_add_item_format(icq_header_tree, 418c823 < proto_tree_add_item_format(icq_tree, --- > proto_tree_add_item_format(icq_header_tree, 425c830 < proto_tree_add_text(icq_tree, --- > proto_tree_add_text(icq_header_tree, 429c834 < proto_tree_add_text(icq_tree, --- > proto_tree_add_text(icq_header_tree, 432a838,865 > 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: > icqv5_cmd_send_msg(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; > default: > proto_tree_add_item_format(icq_tree, > hf_icq_cmd, > offset+ICQ5_CL_CMD, > 2, > cmd, > "Command: %d (%s)", cmd, findcmd(clientCmdCode, cmd)); > break; > } 439a873 > 463a898,900 > if (check_col(fd, COL_INFO)) > col_add_fstr(fd, COL_INFO, "ICQv5 %s", findServerCmd(cmd)); > 479c916 < cmd, findcmd(serverCmdCode, cmd)); --- > cmd, findServerCmd(cmd)); 538c975 < fprintf(stderr, "ICQ: Unknown version\n"); --- > fprintf(stderr, "ICQ: Unknown version (%d)\n", version); Index: packet.h =================================================================== RCS file: /cvsroot/ethereal/packet.h,v retrieving revision 1.120 diff -r1.120 packet.h 254a255 > ETT_ICQ_SUBTREE, -- Kojak
- Follow-Ups:
- Re: [ethereal-dev] Packet-icq update
- From: Guy Harris
- Re: [ethereal-dev] Packet-icq update
- Prev by Date: Re: [ethereal-dev] packet-icq.c ICQ dissector
- Next by Date: Re: [ethereal-dev] SIGSEGV while "Match Selected"
- Previous by thread: Re: [ethereal-dev] Comment update on packet-ntp.c
- Next by thread: Re: [ethereal-dev] Packet-icq update
- Index(es):