Huge thanks to our Platinum Members Endace and LiveAction,
and our Silver Member Veeam, for supporting the Wireshark Foundation and project.

Ethereal-dev: [Ethereal-dev] [PATCH] Oscar dissector ICQ and Filetransfer updates

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Jelmer Vernooij <jelmer@xxxxxxxxx>
Date: Thu, 23 Sep 2004 18:50:46 +0200
Hi,

Some more updates to the Oscar dissector:

- Dissect ICQ TLV values
- Dissect channel 1 and channel 2 messages correctly in Oscar (required for dissecting direct connections)

Cheers,

Jelmer
Index: epan/dissectors/packet-aim-oft.c
===================================================================
--- epan/dissectors/packet-aim-oft.c	(revision 12063)
+++ epan/dissectors/packet-aim-oft.c	(working copy)
@@ -44,7 +44,42 @@
 
 static int proto_aim_oft = -1;
 
+static int ett_aim_recvfile = -1;
+static int ett_aim_sendfile = -1;
 
+/* 
+ * cookie (8 chars)
+ * encrypt (uint16)
+ * compress (uint16)
+ * totfiles (uint16)
+ * filesleft (uint16)
+ * totparts (uint16)
+ * partsleft (uint16)
+ * totsize (uint32)
+ * size (uint32)
+ * modtime (uint32)
+ * checksum (uint32)
+ * rfrcsum (uint32)
+ * rfsize (uint32)
+ * cretime (uint32)
+ * rfcsum (uint32)
+ * nrecvd (uint32)
+ * recvscum (uint32)
+ * idstring (32 chars)
+ * flags (uint8)
+ * lnameoffset (uint8)
+ * lsizeoffset (uint8)
+ * unknown (69 chars)
+ * macfileinfo (16 chars)
+ * nencode (uint16)
+ * nlanguage (uint16)
+ * filename (raw, 64 chars)
+ * 
+ * length of file (uint16)
+ * file data
+ */
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_oft(void)
@@ -62,8 +97,8 @@
   proto_aim_oft = proto_register_protocol("AIM OFT", "AIM OFT", "aim_oft");
 
 /* Required function calls to register the header fields and subtrees used */
-/*  proto_register_field_array(proto_aim_oft, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));*/
+/*  proto_register_field_array(proto_aim_oft, hf, array_length(hf));*/
+/*	proto_register_subtree_array(ett, array_length(ett));*/
 }
 
 void
Index: epan/dissectors/packet-aim-messaging.c
===================================================================
--- epan/dissectors/packet-aim-messaging.c	(revision 12063)
+++ epan/dissectors/packet-aim-messaging.c	(working copy)
@@ -60,9 +60,35 @@
   { INCOMING_CH1_ICON_PRESENT, "Icon present", dissect_aim_tlv_value_bytes },
   { INCOMING_CH1_BUDDY_REQ, "Buddy Req", dissect_aim_tlv_value_bytes },
   { INCOMING_CH1_TYPING, "Non-direct connect typing notification", dissect_aim_tlv_value_bytes },
-  { 0, "Unknown", NULL }
+  { 0, "Unknown", NULL },
 };
 
+int dissect_aim_tlv_value_rendezvous ( proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_);
+extern int dissect_aim_tlv_value_capability_data ( proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_);
+
+
+#define INCOMING_CH2_SERVER_ACK_REQ    	   0x0003
+#define INCOMING_CH2_RENDEZVOUS_DATA       0x0005
+
+static const aim_tlv messaging_incoming_ch2_tlvs[] = {
+  { INCOMING_CH2_SERVER_ACK_REQ, "Server Ack Requested", dissect_aim_tlv_value_bytes },
+  { INCOMING_CH2_RENDEZVOUS_DATA, "Rendez Vous Data", dissect_aim_tlv_value_rendezvous },
+  { 0, "Unknown", NULL },
+};
+
+#define RENDEZVOUS_TLV_INT_IP				0x0003
+#define RENDEZVOUS_TLV_EXT_IP				0x0004
+#define RENDEZVOUS_TLV_EXT_PORT				0x0005
+#define RENDEZVOUS_TLV_CAPABILITY_DATA		0x2711
+
+static const aim_tlv rendezvous_tlvs[] = {
+	{ RENDEZVOUS_TLV_INT_IP, "Internal IP", dissect_aim_tlv_value_ipv4 },
+	{ RENDEZVOUS_TLV_EXT_IP, "External IP", dissect_aim_tlv_value_ipv4 },
+	{ RENDEZVOUS_TLV_EXT_PORT, "External Port", dissect_aim_tlv_value_uint16 },
+	{ RENDEZVOUS_TLV_CAPABILITY_DATA, "Capability Data", dissect_aim_tlv_value_capability_data },
+	{ 0, "Unknown", NULL },
+};
+
 #define MINITYPING_FINISHED_SIGN			0x0000
 #define MINITYPING_TEXT_TYPED_SIGN			0x0001
 #define MINITYPING_BEGUN_SIGN				0x0002
@@ -74,6 +100,17 @@
 	{0, NULL }
 };
 
+#define RENDEZVOUS_MSG_REQUEST 		0
+#define RENDEZVOUS_MSG_CANCEL		1
+#define RENDEZVOUS_MSG_ACCEPT 		2
+
+static const value_string rendezvous_msg_types[] = {
+	{ RENDEZVOUS_MSG_REQUEST, "Request" },
+	{ RENDEZVOUS_MSG_CANCEL, "Cancel" },
+	{ RENDEZVOUS_MSG_ACCEPT, "Accept" },
+	{ 0, "Unknown" },
+};
+
 #define EVIL_ORIGIN_ANONYMOUS		1
 #define EVIL_ORIGIN_NONANONYMOUS 	2
 
@@ -100,18 +137,39 @@
 static int hf_aim_icbm_evil = -1;
 static int hf_aim_evil_warn_level = -1;
 static int hf_aim_evil_new_warn_level = -1;
+static int hf_aim_rendezvous_msg_type = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_messaging = -1;
+static gint ett_aim_rendezvous_data = -1;
 
+int dissect_aim_tlv_value_rendezvous ( proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
+{
+	int offset = 0;
+	proto_tree *entry = proto_item_add_subtree(ti, ett_aim_rendezvous_data);
+	proto_tree_add_item(entry, hf_aim_rendezvous_msg_type, tvb, offset, 2, FALSE);
+	offset+=2;
+	
+	proto_tree_add_item(entry, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
+	offset += 8;
+
+	offset = dissect_aim_capability(entry, tvb, offset);
+
+	return dissect_aim_tlv_sequence(tvb, pinfo, offset, entry, rendezvous_tlvs);
+}
+
 static int dissect_aim_msg_outgoing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *msg_tree)
 {
 	int offset = 0;
+	const aim_tlv *ch_tlvs = NULL;
+	guint16 channel_id;
+	
 	/* ICBM Cookie */
 	proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
 	offset += 8;
 
 	/* Message Channel ID */
+	channel_id = tvb_get_ntohs(tvb, offset);
 	proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
 						FALSE);
 	offset += 2;
@@ -127,21 +185,22 @@
 
 	offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
 
-	while(tvb_reported_length_remaining(tvb, offset) > 0) {
-		/* djh - Note that we reuse the "incoming ch1 tlv" set even though this
-		   is outgoing.  We may need to split this to a separate TLV set, but
-		   so far I haven't seen the need @@@@@@@@ */
-		offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree, 
-								 messaging_incoming_ch1_tlvs);
+	switch(channel_id) {
+	case 1: ch_tlvs = messaging_incoming_ch1_tlvs; break;
+	case 2: ch_tlvs = messaging_incoming_ch2_tlvs; break;
+	default: return offset;
 	}
-
-	return offset;
+			
+	return dissect_aim_tlv_sequence(tvb, pinfo, offset, msg_tree, ch_tlvs);
 }
 
 
 static int dissect_aim_msg_incoming(tvbuff_t *tvb, packet_info *pinfo, proto_tree *msg_tree)
 {
 	int offset = 0;
+	const aim_tlv *ch_tlvs;
+	guint16 channel_id; 
+	
 	/* ICBM Cookie */
 	proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
 	offset += 8;
@@ -149,12 +208,19 @@
 	/* Message Channel ID */
 	proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
 						FALSE);
+	channel_id = tvb_get_ntohs(tvb, offset);
 	offset += 2;
 
 	offset = dissect_aim_userinfo(tvb, pinfo, offset, msg_tree);
+				
+	switch(channel_id) {
+	case 1: ch_tlvs = messaging_incoming_ch1_tlvs; break;
+	case 2: ch_tlvs = messaging_incoming_ch2_tlvs; break;
+	default: return offset;
+	}
 
 	return dissect_aim_tlv_sequence(tvb, pinfo, offset, msg_tree, 
-								 messaging_incoming_ch1_tlvs);
+								 ch_tlvs);
 }
 
 static int dissect_aim_msg_params(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *msg_tree)
@@ -202,8 +268,8 @@
 	{ 0x0003, "Reset ICBM Parameter", NULL },
 	{ 0x0004, "Request Parameter Info", NULL},
 	{ 0x0005, "Parameter Info", dissect_aim_msg_params },
-	{ 0x0006, "Incoming", dissect_aim_msg_incoming },
-	{ 0x0007, "Outgoing", dissect_aim_msg_outgoing },
+	{ 0x0006, "Outgoing", dissect_aim_msg_outgoing },
+	{ 0x0007, "Incoming", dissect_aim_msg_incoming },
 	{ 0x0008, "Evil Request", dissect_aim_msg_evil_req },
 	{ 0x0009, "Evil Response", dissect_aim_msg_evil_repl  },
 	{ 0x000a, "Missed Call", NULL },
@@ -267,11 +333,15 @@
 		{ &hf_aim_icbm_notification_type,
 			{ "Notification Type", "aim.notification.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
 		},
+		{ &hf_aim_rendezvous_msg_type,
+			{ "Message Type", "aim.rendezvous.msg_type", FT_UINT16, BASE_HEX, VALS(rendezvous_msg_types), 0x0, "", HFILL },
+		},
 	};
 
 	/* Setup protocol subtree array */
 	static gint *ett[] = {
 		&ett_aim_messaging,
+		&ett_aim_rendezvous_data,
 	};
 
 	/* Register the protocol name and description */
Index: epan/dissectors/packet-aim.c
===================================================================
--- epan/dissectors/packet-aim.c	(revision 12063)
+++ epan/dissectors/packet-aim.c	(working copy)
@@ -231,8 +231,8 @@
 };
 
 
-static int dissect_aim_tlv_value_userstatus(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb);
-static int dissect_aim_tlv_value_dcinfo(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb);
+static int dissect_aim_tlv_value_userstatus(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_);
+static int dissect_aim_tlv_value_dcinfo(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_);
 
 #define AIM_ONLINEBUDDY_USERCLASS      0x0001
 #define AIM_ONLINEBUDDY_ONSINCE        0x0003
@@ -674,7 +674,8 @@
 
   proto_tree_add_item (aim_tree, hf_aim_snac_error,
 			   tvb, 0, 2, FALSE);
-  return tvb_length_remaining(tvb, 2);
+  
+  return dissect_aim_tlv_sequence(tvb, pinfo, 2, aim_tree, client_tlvs);
 }
 
 int dissect_aim_userinfo(tvbuff_t *tvb, packet_info *pinfo, 
@@ -866,19 +867,21 @@
    return offset+buddyname_length;
 }
 
-typedef struct _e_uuid_t {
-    guint32 Data1;
-    guint16 Data2;
-    guint16 Data3;
-    guint8 Data4[8];
-} e_uuid_t;
+typedef struct _aim_client_capability
+{
+	const char *name;
+	e_uuid_t clsid;	
+} aim_client_capability;
 
-typedef struct _aim_client_capabilities {
-	const char *description;
-	e_uuid_t clsid;
-} aim_client_capabilities;
+static const aim_client_capability known_client_caps[] = {
+	{ "Send File", 
+	  {0x09461343, 0x4c7f, 0x11d1,
+	    { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
 
-static const aim_client_capabilities client_caps[] = {
+	{ "Recv File",
+	    { 0x09461348, 0x4c7f, 0x11d1,
+		   { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+	
 	{ "iChat",
 	 {0x09460000, 0x4c7f, 0x11d1, 
 	   { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
@@ -911,15 +914,6 @@
 	 {0x09461341, 0x4c7f, 0x11d1, 
 		 { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
 
-	{ "Send File",
-	 {0x09461343, 0x4c7f, 0x11d1, 
-		 { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
-
-	{ "Receive File",
-	 {0x09461348, 0x4c7f, 0x11d1,
-		 { 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
-
-
 	{ "Direct ICQ Communication",
 	 {0x09461344, 0x4c7f, 0x11d1, 
 		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
@@ -936,7 +930,6 @@
 	 {0x09461347, 0x4c7f, 0x11d1,
 		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
 
-
 	{ "ICQ Server Relaying",
 	 {0x09461349, 0x4c7f, 0x11d1,
 		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
@@ -997,11 +990,54 @@
 	 {0x0946f003, 0x4c7f, 0x11d1,
 		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
 
-	{ "Unknown", {0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } }
+	{ NULL, {0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } }
 };
 
-int dissect_aim_tlv_value_client_capabilities(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+const aim_client_capability *aim_find_capability ( e_uuid_t clsid)
 {
+	int i;
+
+	for(i = 0; known_client_caps[i].name; i++) 
+	{
+		const aim_client_capability *caps = &(known_client_caps[i]);
+
+		if(memcmp(&(caps->clsid), &clsid, sizeof(e_uuid_t)) == 0)
+			return caps;
+	}
+
+	return NULL;
+}
+
+int dissect_aim_tlv_value_capability_data ( proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb _U_, packet_info *pinfo _U_)
+{
+	return 0;
+}
+
+int dissect_aim_capability(proto_tree *entry, tvbuff_t *tvb, int offset)
+{
+	const aim_client_capability *caps = NULL;
+	e_uuid_t clsid;
+
+	clsid.Data1 = tvb_get_ntohl(tvb, offset);
+	clsid.Data2 = tvb_get_ntohs(tvb, offset+4);
+	clsid.Data3 = tvb_get_ntohs(tvb, offset+6);
+	tvb_memcpy(tvb, clsid.Data4, offset+8, 8);
+
+	caps = aim_find_capability(clsid);
+
+	proto_tree_add_text(entry, tvb, offset, 16, 
+		"%s {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 
+		caps?caps->name:"Unknown", clsid.Data1, clsid.Data2, 
+		clsid.Data3, clsid.Data4[0], clsid.Data4[1], clsid.Data4[2], 
+		clsid.Data4[3], clsid.Data4[4],	clsid.Data4[5], clsid.Data4[6], 
+			clsid.Data4[7]
+	);
+
+	return offset+16;
+}
+
+int dissect_aim_tlv_value_client_capabilities(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
+{
 	int offset = 0;
 	proto_tree *entry;
 
@@ -1010,38 +1046,13 @@
 	entry = proto_item_add_subtree(ti, ett_aim_client_capabilities);
 	
   	while (tvb_length_remaining(tvb, offset) > 0) {
-		int i;
-		const aim_client_capabilities *caps = NULL;
-		e_uuid_t clsid;
-
-		clsid.Data1 = tvb_get_ntohl(tvb, offset);
-		clsid.Data2 = tvb_get_ntohs(tvb, offset+4);
-		clsid.Data3 = tvb_get_ntohs(tvb, offset+6);
-		tvb_memcpy(tvb, clsid.Data4, offset+8, 8);
-
-		for(i = 0; client_caps[i].description; i++) {
-
-			if(memcmp(&(client_caps[i].clsid), &clsid, sizeof(e_uuid_t)) == 0) {
-				caps = &client_caps[i];
-				break;
-			}
-		}
-
-		proto_tree_add_text(entry, tvb, offset, 16, 
-			"%s {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 
-			caps?caps->description:"Unknown", clsid.Data1, clsid.Data2, 
-			clsid.Data3, clsid.Data4[0], clsid.Data4[1], clsid.Data4[2], 
-			clsid.Data4[3], clsid.Data4[4],	clsid.Data4[5], clsid.Data4[6], 
-			clsid.Data4[7]
-			);
-
-		offset+=16;
+		offset = dissect_aim_capability(entry, tvb, offset);
 	}
 
 	return tvb_length(tvb);
 }
 
-int dissect_aim_tlv_value_time(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+int dissect_aim_tlv_value_time(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
 {
 	/* FIXME */
 	return tvb_length(tvb);
@@ -1067,20 +1078,20 @@
 	return offset+len;
 }
 
-int dissect_aim_tlv_value_userclass(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb)
+int dissect_aim_tlv_value_userclass(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
 {
 	guint16 value16 = tvb_get_ntohs(tvb, 0);
 	proto_item_set_text(ti, "Value: 0x%04x", value16);
 	return dissect_aim_userclass(tvb, 0, 2, ti, value16);
 }
 
-static int dissect_aim_tlv_value_userstatus(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb)
+static int dissect_aim_tlv_value_userstatus(proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
 {
 	/* FIXME */
 	return tvb_length(tvb);
 }
 
-static int dissect_aim_tlv_value_dcinfo(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb)
+static int dissect_aim_tlv_value_dcinfo(proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
 {
 	int offset = 0;
 	
@@ -1101,7 +1112,7 @@
 	return offset;
 }
 
-int dissect_aim_tlv_value_string (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb)
+int dissect_aim_tlv_value_string (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_)
 {
    guint8 *buf;
    gint string_len;
@@ -1113,37 +1124,37 @@
    return string_len;
 }
 
-int dissect_aim_tlv_value_bytes (proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb _U_)
+int dissect_aim_tlv_value_bytes (proto_item *ti _U_, guint16 valueid _U_, tvbuff_t *tvb _U_, packet_info *pinfo _U_)
 {
    return tvb_length(tvb);
 }
 
-int dissect_aim_tlv_value_uint8 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+int dissect_aim_tlv_value_uint8 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_){
   guint8 value8 = tvb_get_guint8(tvb, 0);
   proto_item_set_text(ti, "Value: %d", value8);
   return 1;
 }
 
-int dissect_aim_tlv_value_uint16 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+int dissect_aim_tlv_value_uint16 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_){
   guint16 value16 = tvb_get_ntohs(tvb, 0);
   proto_item_set_text(ti, "Value: %d", value16);
   return 2;
 }
 
-int dissect_aim_tlv_value_ipv4 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+int dissect_aim_tlv_value_ipv4 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_){
   /* FIXME: Somewhat more readable format ? */
   guint32 value32 = tvb_get_ntoh24(tvb, 0);
   proto_item_set_text(ti, "Value: %d", value32);
   return 4;
 }
 
-int dissect_aim_tlv_value_uint32 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+int dissect_aim_tlv_value_uint32 (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_){
   guint32 value32 = tvb_get_ntoh24(tvb, 0);
   proto_item_set_text(ti, "Value: %d", value32);
   return 4;
 }
 
-int dissect_aim_tlv_value_messageblock (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb){
+int dissect_aim_tlv_value_messageblock (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *pinfo _U_){
   proto_tree *entry;
   guint8 *buf;
   guint16 featurelen;
@@ -1262,7 +1273,7 @@
 			      "Value");
 	
     if (tmp[i].dissector) {
-      tmp[i].dissector(ti1, valueid, tvb_new_subset(tvb, offset, length, length));
+      tmp[i].dissector(ti1, valueid, tvb_new_subset(tvb, offset, length, length), pinfo);
     } 
 
     offset += length;
Index: epan/dissectors/packet-aim.h
===================================================================
--- epan/dissectors/packet-aim.h	(revision 12063)
+++ epan/dissectors/packet-aim.h	(working copy)
@@ -25,12 +25,15 @@
 #ifndef __PACKET_AIM_H__
 #define __PACKET_AIM_H__
 
+/* For e_uuid_t */
+#include "packet-dcerpc.h"
+
 #define MAX_BUDDYNAME_LENGTH 30
 
 typedef struct _aim_tlv {
   guint16 valueid;
   char *desc;
-  int (*dissector) (proto_item *ti, guint16 value_id, tvbuff_t *tvb);
+  int (*dissector) (proto_item *ti, guint16 value_id, tvbuff_t *tvb, packet_info *);
 } aim_tlv;
 
 struct aiminfo {
@@ -71,17 +74,18 @@
 const aim_family *aim_get_family( guint16 family );
 const aim_subtype *aim_get_subtype( guint16 family, guint16 subtype);
 
-int dissect_aim_tlv_value_string(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_uint8(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_uint16(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_uint32(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_bytes(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_ipv4(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_time(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_client_capabilities(proto_item *ti, guint16, tvbuff_t *);
+int dissect_aim_tlv_value_string(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_uint8(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_uint16(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_uint32(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_bytes(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_ipv4(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_time(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_client_capabilities(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_capability(proto_tree *entry, tvbuff_t *tvb, int offset);
 int dissect_aim_userclass(tvbuff_t *tvb, int offset, int len, proto_item *ti, guint32 flags);
-int dissect_aim_tlv_value_userclass(proto_item *ti, guint16, tvbuff_t *);
-int dissect_aim_tlv_value_messageblock (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb);
+int dissect_aim_tlv_value_userclass(proto_item *ti, guint16, tvbuff_t *, packet_info *);
+int dissect_aim_tlv_value_messageblock (proto_item *ti, guint16 valueid _U_, tvbuff_t *tvb, packet_info *);
 
 extern const aim_tlv client_tlvs[];
 extern const aim_tlv onlinebuddy_tlvs[];
Index: epan/dissectors/packet-aim-signon.c
===================================================================
--- epan/dissectors/packet-aim-signon.c	(revision 12063)
+++ epan/dissectors/packet-aim-signon.c	(working copy)
@@ -121,12 +121,30 @@
 	return offset;
 }
 
+static int dissect_aim_tlv_value_registration(proto_item *ti _U_, guint16 value_id _U_, tvbuff_t *tvb _U_, packet_info *pinfo)
+{
+	/* FIXME */
+	return 0;
+}
+
+#define REG_TLV_REGISTRATION_INFO 	0x0001
+
+static const aim_tlv registration_tlvs[] = {
+	{ REG_TLV_REGISTRATION_INFO, "Registration Info", dissect_aim_tlv_value_registration },
+	{ 0, "Unknown", NULL },
+};
+
+static int dissect_aim_snac_register (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+	return dissect_aim_tlv(tvb, pinfo, 0, tree, registration_tlvs);
+}
+
 static const aim_subtype aim_fnac_family_signon[] = {
 	{ 0x0001, "Error", dissect_aim_snac_error },
 	{ 0x0002, "Logon", dissect_aim_snac_signon_logon },
 	{ 0x0003, "Logon Reply", dissect_aim_snac_signon_logon_reply },
-	{ 0x0004, "Request UIN", NULL },
-	{ 0x0005, "New UIN response", NULL },
+	{ 0x0004, "Request UIN", dissect_aim_snac_register },
+	{ 0x0005, "New UIN response", dissect_aim_snac_register },
 	{ 0x0006, "Sign-on", dissect_aim_snac_signon_signon },
 	{ 0x0007, "Sign-on Reply", dissect_aim_snac_signon_signon_reply },
 	{ 0x000a, "Server SecureID Request", NULL },
Index: epan/dissectors/packet-image-jfif.c
===================================================================
--- epan/dissectors/packet-image-jfif.c	(revision 12063)
+++ epan/dissectors/packet-image-jfif.c	(working copy)
@@ -1193,7 +1193,7 @@
 
 	jfif_handle = create_dissector_handle(dissect_jfif, proto_jfif);
 
-	/* Register the GIF media type */
+	/* Register the JPEG media type */
 	dissector_add_string("media_type", "image/jfif", jfif_handle);
 	dissector_add_string("media_type", "image/jpg", jfif_handle);
 	dissector_add_string("media_type", "image/jpeg", jfif_handle);
Index: epan/dissectors/packet-aim-icq.c
===================================================================
--- epan/dissectors/packet-aim-icq.c	(revision 12063)
+++ epan/dissectors/packet-aim-icq.c	(working copy)
@@ -44,12 +44,14 @@
 
 #define ICQ_CLI_OFFLINE_MESSAGE_REQ 	0x003c
 #define ICQ_CLI_DELETE_OFFLINE_MSGS		0x003e
+#define ICQ_SRV_OFFLINE_MSGS			0x0041
 #define ICQ_SRV_END_OF_OFFLINE_MSGS		0x0042
 #define ICQ_CLI_META_INFO_REQ			0x07d0
 #define ICQ_SRV_META_INFO_REPL			0x07da
 
 static const value_string aim_icq_data_types[] = {
   { ICQ_CLI_OFFLINE_MESSAGE_REQ, "Offline Message Request" },
+  { ICQ_SRV_OFFLINE_MSGS, "Offline Messages Reply" },
   { ICQ_SRV_END_OF_OFFLINE_MSGS, "End Of Offline Messages Reply" },
   { ICQ_CLI_DELETE_OFFLINE_MSGS, "Delete Offline Messages Request" },
   { ICQ_CLI_META_INFO_REQ, "Metainfo Request" },
@@ -58,7 +60,7 @@
 };
 
 
-static int dissect_aim_tlv_value_icq(proto_item *ti, guint16 subtype, tvbuff_t *tvb);
+static int dissect_aim_tlv_value_icq(proto_item *ti, guint16 subtype, tvbuff_t *tvb, packet_info *pinfo _U_);
 
 #define TLV_ICQ_META_DATA 			  0x0001
 
@@ -77,27 +79,124 @@
 static gint hf_icq_tlv_data_chunk_size = -1;
 static gint hf_icq_tlv_request_owner_uid = -1;
 static gint hf_icq_tlv_request_type = -1;
+static gint hf_icq_meta_subtype = -1;
 static gint hf_icq_tlv_request_seq_num = -1;
+static gint hf_icq_dropped_msg_flag = -1;
 
-static int dissect_aim_tlv_value_icq(proto_item *ti _U_, guint16 subtype _U_, tvbuff_t *tvb _U_)
+
+static struct
 {
+	guint16 subtype;
+	char *name;
+	int (*dissector) (tvbuff_t *, packet_info *, proto_tree *);
+} icq_calls [] = {
+	{ 0x0001, "Server Error Reply", NULL },
+	{ 0x0064, "Set User Home Info Reply", NULL },
+	{ 0x006e, "Set User Work Info Reply", NULL },
+	{ 0x0078, "Set User More Info Reply", NULL },
+	{ 0x0082, "Set User Notes Info Reply", NULL },
+	{ 0x0087, "Set User Email Info Reply", NULL },
+	{ 0x008c, "Set User Interests Info Reply", NULL },
+	{ 0x0096, "Set User Affiliations Info Reply", NULL },
+	{ 0x00a0, "Set User Permissions Reply", NULL },
+	{ 0x00aa, "Set User Password Reply", NULL },
+	{ 0x00b4, "Unregister Account Reply", NULL },
+	{ 0x00be, "Set User Homepage Category Reply", NULL },
+	{ 0x00c8, "User Basic Info Reply", NULL },
+	{ 0x00d2, "User Work Info Reply", NULL },
+	{ 0x00dc, "User More Info Reply", NULL },
+	{ 0x00e6, "User Notes Info Reply", NULL },
+	{ 0x00eb, "User Extended Email Reply", NULL },
+	{ 0x00f0, "User Interests Info Reply", NULL },
+	{ 0x00fa, "User Affiliations Info Reply", NULL },
+	{ 0x0104, "Short User Info Reply", NULL },
+	{ 0x010e, "User Homepage Category Reply", NULL },
+	{ 0x01a4, "Search: User found", NULL },
+	{ 0x0302, "Registration Stats Reply", NULL },
+	{ 0x0366, "Random Search Server Reply", NULL },
+	{ 0x03ea, "Set User Home Info Request", NULL },
+	{ 0x03f3, "Set User Work Info Request", NULL },
+	{ 0x03fd, "Set User More Info Request", NULL },
+	{ 0x0406, "Set User Notes Request", NULL },
+	{ 0x040b, "Set User Extended Email Info Request", NULL },
+	{ 0x0410, "Set User Interests Info Request", NULL },
+	{ 0x041a, "Set User Affiliations Info Request", NULL },
+	{ 0x0424, "Set User Permissions Info Request", NULL },
+	{ 0x042e, "Change User Password Request", NULL },
+	{ 0x0442, "Set User Homepage Category Request", NULL },
+	{ 0x04b2, "Fullinfo Request", NULL },
+	{ 0x04ba, "Short User Info Request", NULL },
+	{ 0x04c4, "Unregister User Request", NULL },
+	{ 0x0515, "Search By Details Request", NULL },
+	{ 0x0569, "Search By UIN Request", NULL },
+	{ 0x055f, "Whitepages Search Request", NULL },
+	{ 0x0573, "Search By Email Request", NULL },
+	{ 0x074e, "Random Chat User Search Request", NULL },
+	{ 0x0898, "Server Variable Request (XML)", NULL },
+	{ 0x0aa5, "Registration Report Request", NULL },
+	{ 0x0aaf, "Shortcut Bar Stats Report Request", NULL },
+	{ 0x0c3a, "Save Info Request", NULL },
+	{ 0x1482, "Send SMS Request", NULL },
+	{ 0x2008, "Spam Report Request", NULL },
+	{ 0x08a2, "Server Variable Reply (XML)", NULL },
+	{ 0x0c3f, "Set Fullinfo Reply", NULL },
+	{ 0x2012, "User Spam Report Reply", NULL },
+	{ 0, NULL, NULL },
+};
+
+
+static int dissect_aim_tlv_value_icq(proto_item *ti _U_, guint16 subtype _U_, tvbuff_t *tvb _U_, packet_info *pinfo)
+{
 	int offset = 0;
+	int i;
+	proto_item *subtype_item;
+	guint16 req_type, req_subtype;
 	proto_tree *t = proto_item_add_subtree(ti, ett_aim_icq_tlv);
 
-	proto_tree_add_item(t, hf_icq_tlv_data_chunk_size, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+	proto_tree_add_item(t, hf_icq_tlv_data_chunk_size, tvb, offset, 2, TRUE);
 	offset += 2;
 	
-	proto_tree_add_item(t, hf_icq_tlv_request_owner_uid, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));
+	proto_tree_add_item(t, hf_icq_tlv_request_owner_uid, tvb, offset, 4, TRUE);
 	offset += 4;
 
-	proto_tree_add_item(t, hf_icq_tlv_request_type, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+	proto_tree_add_item(t, hf_icq_tlv_request_type, tvb, offset, 2, TRUE);
+	req_type = tvb_get_letohs(tvb, offset);
 	offset += 2;
 
-
-	proto_tree_add_item(t, hf_icq_tlv_request_seq_num, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+	proto_tree_add_item(t, hf_icq_tlv_request_seq_num, tvb, offset, 2, TRUE);
 	offset += 2;
 
-	return 0;
+	switch(req_type) {
+	case ICQ_CLI_OFFLINE_MESSAGE_REQ: return offset;
+	case ICQ_CLI_DELETE_OFFLINE_MSGS: return offset;
+	case ICQ_SRV_OFFLINE_MSGS:
+		/* FIXME */
+		break;
+	case ICQ_SRV_END_OF_OFFLINE_MSGS: 
+		proto_tree_add_item(t, hf_icq_dropped_msg_flag, tvb, offset, 1, TRUE);
+		return offset+1;
+	case ICQ_CLI_META_INFO_REQ:
+	case ICQ_SRV_META_INFO_REPL:
+		req_subtype = tvb_get_letohs(tvb, offset);
+		subtype_item = proto_tree_add_item(t, hf_icq_meta_subtype, tvb, offset, 2, TRUE); offset+=2;
+		
+		for(i = 0; icq_calls[i].name; i++) {
+			if(icq_calls[i].subtype == req_subtype) break;
+		}
+
+		if(check_col(pinfo->cinfo, COL_INFO)) 
+			col_set_str(pinfo->cinfo, COL_INFO, icq_calls[i].name?icq_calls[i].name:"Unknown ICQ Meta Call");
+
+		proto_item_append_text(subtype_item, " (%s)", icq_calls[i].name?icq_calls[i].name:"Unknown");
+
+		if(icq_calls[i].dissector) 
+			return icq_calls[i].dissector(tvb_new_subset(tvb, offset, -1, -1), pinfo, t);
+
+	default:
+		break;
+	}
+
+	return offset;
 }
 
 static int dissect_aim_icq_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
@@ -107,8 +206,8 @@
 
 static const aim_subtype aim_fnac_family_icq[] = {
   { 0x0001, "Error", dissect_aim_snac_error },
-  { 0x0002, "Login Request", dissect_aim_icq_tlv },
-  { 0x0003, "Login Response", dissect_aim_icq_tlv },
+  { 0x0002, "ICQ Request", dissect_aim_icq_tlv },
+  { 0x0003, "ICQ Response", dissect_aim_icq_tlv },
   { 0x0006, "Auth Request", NULL },
   { 0x0007, "Auth Response", NULL },
   { 0, NULL, NULL }
@@ -134,6 +233,12 @@
 	  { &hf_icq_tlv_request_seq_num,
 	    {"Request Sequence Number", "aim_icq.request_seq_number", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL},
 	  },
+	  { &hf_icq_dropped_msg_flag,
+		{"Dropped messages flag", "aim_icq.offline_msgs.dropped_flag", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL },
+	  },
+	  { &hf_icq_meta_subtype,
+		{"Meta Request Subtype", "aim_icq.subtype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+	  },
   };
 
 /* Setup protocol subtree array */