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





