Ethereal-dev: [Ethereal-dev] [PATCH] New Oscar structure + minor 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: Mon, 20 Sep 2004 21:18:48 +0200
Hi,

This patch removes some code duplication from the Oscar 
dissector (reduces the number of lines by 500) by providing a 
custom registration function for oscar families (aim_init_family). 
This also fixes a number of issues with column names.

The patch also contains minor updates such as adding support for the 
Capability Info TLV on users. 

There is still one compile-time warning - something that I hope to
address later (not broken because of this patch, it has never done
anything).

Cheers,

Jelmer
Index: epan/dissectors/packet-aim-directory.c
===================================================================
--- epan/dissectors/packet-aim-directory.c	(revision 12042)
+++ epan/dissectors/packet-aim-directory.c	(working copy)
@@ -41,56 +41,28 @@
 
 #define FAMILY_DIRECTORY  0x000F
 
-#define FAMILY_DIRECTORY_ERROR			    0x0001
-#define FAMILY_DIRECTORY_SEARCH_USER_REQ	0x0002
-#define FAMILY_DIRECTORY_SEARCH_USER_REPL   0x0003
-#define FAMILY_DIRECTORY_INTERESTS_LIST_REQ 0x0004
-#define FAMILY_DIRECTORY_INTERESTS_LIST_REP 0x0005
-
-static const value_string aim_fnac_family_directory[] = {
-	{ FAMILY_DIRECTORY_ERROR, "Error" },
-	{ FAMILY_DIRECTORY_SEARCH_USER_REQ, "Client search for user request" },
-	{ FAMILY_DIRECTORY_SEARCH_USER_REPL, "Server reply for search request (found users)" },
-	{ FAMILY_DIRECTORY_INTERESTS_LIST_REQ, "Request interests list from server" },
-	{ FAMILY_DIRECTORY_INTERESTS_LIST_REP, "Interests list" },
-	{ 0, NULL },
-};
-
 static int proto_aim_directory = -1;
 static int ett_aim_directory = -1;
 
-static int dissect_aim_directory(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int dissect_aim_directory_user_repl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-	struct aiminfo *aiminfo = pinfo->private_data;
-	proto_item *ti;
 	int offset = 0;
-	proto_tree *directory_tree = NULL;
-
-    if(tree) {
-    	ti = proto_tree_add_text(tree, tvb, 0, -1, "Directory Service");
-    	directory_tree = proto_item_add_subtree(ti, ett_aim_directory);
-   	}
-
-	switch(aiminfo->subtype) {
-	case FAMILY_DIRECTORY_ERROR:
-		return dissect_aim_snac_error(tvb, pinfo, 0, directory_tree);
-	case FAMILY_DIRECTORY_INTERESTS_LIST_REQ:
-		return 0;
-	case FAMILY_DIRECTORY_SEARCH_USER_REQ:
-		/* FIXME */
-		return 0;
-	case FAMILY_DIRECTORY_SEARCH_USER_REPL:
-		while (tvb_length_remaining(tvb, offset) > 0) {
-			offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
-		}
-		return offset;
-	case FAMILY_DIRECTORY_INTERESTS_LIST_REP:
-		/* FIXME */
-		return 0;
+	while (tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
 	}
-	return 0;
+	return offset;
 }
 
+static const aim_subtype aim_fnac_family_directory[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Client search for user request", NULL },
+	{ 0x0003, "Server reply for search request (found users)", dissect_aim_directory_user_repl },
+	{ 0x0004, "Request interests list from server", NULL },
+	{ 0x0005, "Interests list", NULL },
+	{ 0, NULL, NULL },
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_directory(void)
@@ -117,8 +89,5 @@
 void
 proto_reg_handoff_aim_directory(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_directory, proto_aim_directory);
-  dissector_add("aim.family", FAMILY_DIRECTORY, aim_handle); 
-  aim_init_family(FAMILY_DIRECTORY, "Directory", aim_fnac_family_directory);
+  aim_init_family(proto_aim_directory, ett_aim_directory, FAMILY_DIRECTORY, aim_fnac_family_directory);
 }
Index: epan/dissectors/packet-aim-chatnav.c
===================================================================
--- epan/dissectors/packet-aim-chatnav.c	(revision 12042)
+++ epan/dissectors/packet-aim-chatnav.c	(working copy)
@@ -41,69 +41,24 @@
 
 #define FAMILY_CHAT_NAV   0x000D
 
-/* Family Chat Navigation */
-#define FAMILY_CHATNAV_ERROR          0x0001
-#define FAMILY_CHATNAV_LIMITS_REQ     0x0002
-#define FAMILY_CHATNAV_EXCHANGE_REQ   0x0003
-#define FAMILY_CHATNAV_ROOM_INFO_REQ  0x0004
-#define FAMILY_CHATNAV_ROOMIF_EXT_REQ 0x0005
-#define FAMILY_CHATNAV_MEMBERLIST_REQ 0x0006
-#define FAMILY_CHATNAV_SEARCH_ROOM    0x0007
-#define FAMILY_CHATNAV_CREATE_ROOM    0x0008
-#define FAMILY_CHATNAV_INFO_REPLY     0x0009
-#define FAMILY_CHATNAV_DEFAULT        0xffff
-
-static const value_string aim_fnac_family_chatnav[] = {
-  { FAMILY_CHATNAV_ERROR, "Error" },
-  { FAMILY_CHATNAV_LIMITS_REQ, "Request Limits" },
-  { FAMILY_CHATNAV_EXCHANGE_REQ, "Request Exchange" },
-  { FAMILY_CHATNAV_ROOM_INFO_REQ, "Request Room Information" },
-  { FAMILY_CHATNAV_ROOMIF_EXT_REQ, "Request Extended Room Information" },
-  { FAMILY_CHATNAV_MEMBERLIST_REQ, "Request Member List" },
-  { FAMILY_CHATNAV_SEARCH_ROOM, "Search Room" },
-  { FAMILY_CHATNAV_CREATE_ROOM, "Create" },
-  { FAMILY_CHATNAV_INFO_REPLY, "Info" },
-  { FAMILY_CHATNAV_DEFAULT, "ChatNav Default" },
-  { 0, NULL }
+static const aim_subtype aim_fnac_family_chatnav[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Request Limits", NULL },
+  { 0x0003, "Request Exchange", NULL },
+  { 0x0004, "Request Room Information", NULL },
+  { 0x0005, "Request Extended Room Information", NULL },
+  { 0x0006, "Request Member List", NULL },
+  { 0x0007, "Search Room", NULL },
+  { 0x0008, "Create", NULL },
+  { 0x0009, "Info", NULL },
+  { 0, NULL, NULL }
 };
 
 /* Initialize the protocol and registered fields */
 static int proto_aim_chatnav = -1;
 
-int ett_aim_chatnav = -1;
+static int ett_aim_chatnav = -1;
 
-static int dissect_aim_chatnav(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
-  struct aiminfo *aiminfo = pinfo->private_data;
-	
-  proto_item *ti;
-  proto_tree *chatnav_tree = NULL;
-
-  if(tree) {
-      ti = proto_tree_add_text(tree, tvb, 0, -1, "Chat Navigation Service");
-      chatnav_tree = proto_item_add_subtree(ti, ett_aim_chatnav);
-  }
-
-  switch(aiminfo->subtype) {
-	  case FAMILY_CHATNAV_ERROR:
-		  return dissect_aim_snac_error(tvb, pinfo, 0, chatnav_tree);
-	case FAMILY_CHATNAV_LIMITS_REQ:
-		  /* No data */
-		  return 0;
-	case FAMILY_CHATNAV_EXCHANGE_REQ:
-	case FAMILY_CHATNAV_ROOM_INFO_REQ:
-	case FAMILY_CHATNAV_ROOMIF_EXT_REQ:
-	case FAMILY_CHATNAV_MEMBERLIST_REQ:
-	case FAMILY_CHATNAV_SEARCH_ROOM:
-	case FAMILY_CHATNAV_CREATE_ROOM:
-	case FAMILY_CHATNAV_INFO_REPLY:
-	case FAMILY_CHATNAV_DEFAULT:
-  /* FIXME */
-	  return 0;
-	default: return 0;
-  }
-}
-
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_chatnav(void)
@@ -130,10 +85,5 @@
 void
 proto_reg_handoff_aim_chatnav(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_chatnav, proto_aim_chatnav);
-  dissector_add("aim.family", FAMILY_CHAT_NAV, aim_handle);
-  
-  aim_init_family(FAMILY_CHAT_NAV, "Chat Navigation", aim_fnac_family_chatnav);
+	aim_init_family(proto_aim_chatnav, ett_aim_chatnav, FAMILY_CHAT_NAV, aim_fnac_family_chatnav);
 }
Index: epan/dissectors/packet-aim-stats.c
===================================================================
--- epan/dissectors/packet-aim-stats.c	(revision 12042)
+++ epan/dissectors/packet-aim-stats.c	(working copy)
@@ -41,28 +41,21 @@
 
 #define FAMILY_STATS      0x000B
 
-/* Family User Stats */
-#define FAMILY_STATS_ERROR             0x0001
-#define FAMILY_STATS_SETREPORTINTERVAL 0x0002
-#define FAMILY_STATS_REPORTREQ         0x0003
-#define FAMILY_STATS_REPORTACK         0x0004
-#define FAMILY_STATS_DEFAULT           0xffff
-
-static const value_string aim_fnac_family_stats[] = {
-  { FAMILY_STATS_ERROR, "Error" },
-  { FAMILY_STATS_SETREPORTINTERVAL, "Set Report Interval" },
-  { FAMILY_STATS_REPORTREQ, "Report Request" },
-  { FAMILY_STATS_REPORTACK, "Report Ack" },
-  { FAMILY_STATS_DEFAULT, "Stats Default" },
-  { 0, NULL }
-};
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_stats = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_stats    = -1;
 
+static const aim_subtype aim_fnac_family_stats[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Set Report Interval", NULL },
+  { 0x0003, "Report Request", NULL },
+  { 0x0004, "Report Ack", NULL },
+  { 0, NULL, NULL }
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_stats(void)
@@ -90,8 +83,5 @@
 void
 proto_reg_handoff_aim_stats(void)
 {
-  /*dissector_handle_t aim_handle;*/
-/*FIXME:  aim_handle = new_create_dissector_handle(dissect_aim_snac_stats, proto_aim_stats);
-  dissector_add("aim.family", FAMILY_STATS, aim_handle);*/
-  aim_init_family(FAMILY_STATS, "Statistic", aim_fnac_family_stats);
+  aim_init_family(proto_aim_stats, ett_aim_stats, FAMILY_STATS, aim_fnac_family_stats);
 }
Index: epan/dissectors/packet-aim-translate.c
===================================================================
--- epan/dissectors/packet-aim-translate.c	(revision 12042)
+++ epan/dissectors/packet-aim-translate.c	(working copy)
@@ -41,30 +41,17 @@
 
 #define FAMILY_TRANSLATE  0x000C
 
-/* Family Translation */
-#define FAMILY_TRANSLATE_ERROR        0x0001
-#define FAMILY_TRANSLATE_REQ          0x0002
-#define FAMILY_TRANSLATE_REPL         0x0003
-#define FAMILY_TRANSLATE_DEFAULT      0xffff
-
-static const value_string aim_fnac_family_translate[] = {
-  { FAMILY_TRANSLATE_ERROR, "Error" },
-  { FAMILY_TRANSLATE_REQ, "Translate Request" },
-  { FAMILY_TRANSLATE_REPL, "Translate Reply" },
-  { FAMILY_TRANSLATE_DEFAULT, "Translate Default" },
-  { 0, NULL }
-};
-
 static int proto_aim_translate = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_translate = -1;
 
-static int dissect_aim_translate(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_) {
-	
-	/* FIXME */
-	return 0;
-}
+static const aim_subtype aim_fnac_family_translate[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Translate Request", NULL },
+  { 0x0003, "Translate Reply", NULL },
+  { 0, NULL, NULL }
+};
 
 /* Register the protocol with Ethereal */
 void
@@ -92,8 +79,5 @@
 void
 proto_reg_handoff_aim_translate(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_translate, proto_aim_translate);
-  dissector_add("aim.family", FAMILY_TRANSLATE, aim_handle);
-  aim_init_family(FAMILY_TRANSLATE, "Translate", aim_fnac_family_translate);
+  aim_init_family(proto_aim_translate, ett_aim_translate, FAMILY_TRANSLATE, aim_fnac_family_translate);
 }
Index: epan/dissectors/packet-aim-invitation.c
===================================================================
--- epan/dissectors/packet-aim-invitation.c	(revision 12042)
+++ epan/dissectors/packet-aim-invitation.c	(working copy)
@@ -41,53 +41,29 @@
 
 #define FAMILY_INVITATION 0x0006
 
-/* Family Invitation */
-#define FAMILY_INVITATION_ERROR       0x0001
-#define FAMILY_INVITATION_FRIEND_REQ  0x0002
-#define FAMILY_INVITATION_FRIEND_REPL 0x0003
-#define FAMILY_INVITATION_DEFAULT     0xffff
-
-static const value_string aim_fnac_family_invitation[] = {
-  { FAMILY_INVITATION_ERROR, "Error" },
-  { FAMILY_INVITATION_FRIEND_REQ, "Invite a friend to join AIM" },
-  { FAMILY_INVITATION_FRIEND_REPL, "Invitation Ack" },
-  { FAMILY_INVITATION_DEFAULT, "Invitation Default" },
-  { 0, NULL }
-};
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_invitation = -1;
 
 static int ett_aim_invitation = -1;
 
-static int dissect_aim_invitation(tvbuff_t *tvb, packet_info *pinfo,
-                       proto_tree *tree)
+static int dissect_aim_invitation_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *invite_tree)
 {
-  int offset = 0;
-  struct aiminfo *aiminfo = pinfo->private_data;
-  proto_item *ti = NULL;
-  proto_tree *invite_tree = NULL;
-                                                                                
-  if(tree) {
-	ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Invite Service");
-    invite_tree = proto_item_add_subtree(ti, ett_aim_invitation);
-  }
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, invite_tree, onlinebuddy_tlvs);
+	}
+	return offset;
+}
 
-  switch(aiminfo->subtype) {
- 	case FAMILY_INVITATION_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, invite_tree);
-    case FAMILY_INVITATION_FRIEND_REQ:
-       while(tvb_length_remaining(tvb, offset) > 0) {
-          offset = dissect_aim_tlv(tvb, pinfo, offset, invite_tree, onlinebuddy_tlvs);
-	   }
-	   return 0;
-    case FAMILY_INVITATION_FRIEND_REPL:
-		return 0;
-  }
+static const aim_subtype aim_fnac_family_invitation[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Invite a friend to join AIM", dissect_aim_invitation_req },
+	{ 0x0003, "Invitation Ack", NULL },
+	{ 0, NULL, NULL }
+};
 
-  return 0;
-}
-                                                                                
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_invitation(void)
@@ -108,9 +84,5 @@
 void
 proto_reg_handoff_aim_invitation(void)
 {
-  dissector_handle_t aim_handle;
-  
-  aim_handle = new_create_dissector_handle(dissect_aim_invitation, proto_aim_invitation);
-  dissector_add("aim.family", FAMILY_INVITATION, aim_handle);
-  aim_init_family(FAMILY_INVITATION, "Invitation", aim_fnac_family_invitation);
+  aim_init_family(proto_aim_invitation, ett_aim_invitation, FAMILY_INVITATION, aim_fnac_family_invitation);
 }
Index: epan/dissectors/packet-aim-ssi.c
===================================================================
--- epan/dissectors/packet-aim-ssi.c	(revision 12042)
+++ epan/dissectors/packet-aim-ssi.c	(working copy)
@@ -42,54 +42,7 @@
 
 #define FAMILY_SSI        0x0013
 
-/* Family Server-Stored Buddy Lists */
-#define FAMILY_SSI_ERROR              0x0001
-#define FAMILY_SSI_REQRIGHTS          0x0002
-#define FAMILY_SSI_RIGHTSINFO         0x0003
-#define FAMILY_SSI_REQLIST_FIRSTTIME  0x0004
-#define FAMILY_SSI_REQLIST            0x0005
-#define FAMILY_SSI_LIST               0x0006
-#define FAMILY_SSI_ACTIVATE           0x0007
-#define FAMILY_SSI_ADD                0x0008
-#define FAMILY_SSI_MOD                0x0009
-#define FAMILY_SSI_DEL                0x000a
-#define FAMILY_SSI_SRVACK             0x000e
-#define FAMILY_SSI_NOLIST             0x000f
-#define FAMILY_SSI_EDITSTART          0x0011
-#define FAMILY_SSI_EDITSTOP           0x0012
-#define FAMILY_SSI_GRANT_FUTURE_AUTH  0x0014
-#define FAMILY_SSI_FUTUR_AUTH_GRANTED 0x0015
-#define FAMILY_SSI_SEND_AUTH_REQ      0x0018
-#define FAMILY_SSI_AUTH_REQ           0x0019
-#define FAMILY_SSI_SEND_AUTH_REPLY    0x001a
-#define FAMILY_SSI_AUTH_REPLY         0x001b
-#define FAMILY_SSI_WAS_ADDED          0x001c
 
-static const value_string aim_fnac_family_ssi[] = {
-  { FAMILY_SSI_ERROR, "Error" },
-  { FAMILY_SSI_REQRIGHTS, "Request Rights" },
-  { FAMILY_SSI_RIGHTSINFO, "Rights Info" },
-  { FAMILY_SSI_REQLIST_FIRSTTIME, "Request List (first time)" },
-  { FAMILY_SSI_REQLIST, "Request List" },
-  { FAMILY_SSI_LIST, "List" },
-  { FAMILY_SSI_ACTIVATE, "Activate" },
-  { FAMILY_SSI_ADD, "Add Buddy" },
-  { FAMILY_SSI_MOD, "Modify Buddy" },
-  { FAMILY_SSI_DEL, "Delete Buddy" },
-  { FAMILY_SSI_SRVACK, "Server Ack" },
-  { FAMILY_SSI_NOLIST, "No List" },
-  { FAMILY_SSI_EDITSTART, "Edit Start" },
-  { FAMILY_SSI_EDITSTOP, "Edit Stop" },
-  { FAMILY_SSI_GRANT_FUTURE_AUTH, "Grant Future Authorization to Client" },
-  { FAMILY_SSI_FUTUR_AUTH_GRANTED, "Future Authorization Granted" },
-  { FAMILY_SSI_SEND_AUTH_REQ, "Send Authentication Request" },
-  { FAMILY_SSI_AUTH_REQ, "Authentication Request" },
-  { FAMILY_SSI_SEND_AUTH_REPLY, "Send Authentication Reply" },
-  { FAMILY_SSI_AUTH_REPLY, "Authentication Reply" },
-  { FAMILY_SSI_WAS_ADDED, "Remote User Added Client To List" },
-  { 0, NULL }
-};
-
 #define FAMILY_SSI_TYPE_BUDDY         0x0000
 #define FAMILY_SSI_TYPE_GROUP         0x0001
 #define FAMILY_SSI_TYPE_PERMIT        0x0002
@@ -113,12 +66,9 @@
 
 static const aim_tlv ssi_rightsinfo_tlvs[] = {
 	{ SSI_RIGHTSINFO_TLV_MAX_ITEMS, "Maximums For Items", dissect_aim_tlv_value_bytes }, 
-	{ 0, NULL, NULL },
+	{ 0, "Unknown", NULL },
 };
 
-static int dissect_aim_snac_ssi_list(tvbuff_t *tvb, packet_info *pinfo _U_, 
-				      int offset, proto_tree *tree, guint16 subtype _U_);
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_ssi = -1;
 static int hf_aim_fnac_subtype_ssi_version = -1;
@@ -137,198 +87,187 @@
 static gint ett_ssi      = -1;
 
 static int dissect_ssi_item(tvbuff_t *tvb, packet_info *pinfo _U_, 
-				      int offset, proto_tree *ssi_entry, 
-				      guint16 subtype _U_)
+				      int offset, proto_tree *ssi_entry)
 {
-  guint16 buddyname_length = 0;
-  int endoffset;
-  guint16 tlv_len = 0;
-	 /* Buddy Name Length */
-    buddyname_length = tvb_get_ntohs(tvb, offset);
-    proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_buddyname_len, 
-			tvb, offset, 2, FALSE);
-    offset += 2;
-    
-    /* Buddy Name */
-    if (buddyname_length > 0) {
-      proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_buddyname, tvb, 
-			  offset, buddyname_length, FALSE);
-      offset += buddyname_length;
-    }
-    
-    /* Buddy group ID */
-    proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_gid, tvb, offset, 
-			2, FALSE);
-    offset += 2;
-    
-    /* Buddy ID */
-    proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_bid, tvb, offset, 
-			2, FALSE);
-    offset += 2;
-    
-    /* Buddy Type */
-    proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_type, tvb, offset,
-			2, FALSE);
-    offset += 2;
-    
-    /* Size of the following TLV in bytes (as opposed to the number of 
-       TLV objects in the chain) */
-    tlv_len = tvb_get_ntohs(tvb, offset);
-    proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_tlvlen, tvb, 
-			offset, 2, FALSE);
-    offset += 2;
-    
+	guint16 buddyname_length = 0;
+	int endoffset;
+	guint16 tlv_len = 0;
+
+	/* Buddy Name Length */
+	buddyname_length = tvb_get_ntohs(tvb, offset);
+	proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_buddyname_len, 
+						tvb, offset, 2, FALSE);
+	offset += 2;
+
+	/* Buddy Name */
+	if (buddyname_length > 0) {
+		proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_buddyname, tvb, 
+							offset, buddyname_length, FALSE);
+		offset += buddyname_length;
+	}
+
+	/* Buddy group ID */
+	proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_gid, tvb, offset, 
+						2, FALSE);
+	offset += 2;
+
+	/* Buddy ID */
+	proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_bid, tvb, offset, 
+						2, FALSE);
+	offset += 2;
+
+	/* Buddy Type */
+	proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_type, tvb, offset,
+						2, FALSE);
+	offset += 2;
+
+	/* Size of the following TLV in bytes (as opposed to the number of 
+	   TLV objects in the chain) */
+	tlv_len = tvb_get_ntohs(tvb, offset);
+	proto_tree_add_item(ssi_entry, hf_aim_fnac_subtype_ssi_tlvlen, tvb, 
+						offset, 2, FALSE);
+	offset += 2;
+
 	endoffset = offset;
-    /* For now, we just dump the TLV contents as-is, since there is not a
-       TLV dissection utility that works based on total chain length */
+	/* For now, we just dump the TLV contents as-is, since there is not a
+	   TLV dissection utility that works based on total chain length */
 	while(endoffset < offset+tlv_len) {
-      	endoffset = dissect_aim_tlv(tvb, pinfo, endoffset, ssi_entry, client_tlvs);
-    }
+		endoffset = dissect_aim_tlv(tvb, pinfo, endoffset, ssi_entry, client_tlvs);
+	}
 	return endoffset;
 }
 
-static int dissect_aim_snac_ssi(tvbuff_t *tvb, packet_info *pinfo _U_, 
-				 proto_tree *tree)
+static int dissect_ssi_ssi_item(tvbuff_t *tvb, packet_info *pinfo, 
+				      proto_tree *ssi_entry)
 {
-	struct aiminfo *aiminfo = pinfo->private_data;
+	return dissect_ssi_item(tvb, pinfo, 0, ssi_entry);
+}
+
+
+static int dissect_aim_ssi_rightsinfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ssi_tree)
+{
 	int offset = 0;
-    proto_item *ti = NULL;
-    proto_tree *ssi_tree = NULL;
-                                                                                
-    if(tree) {
-		ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Server Side Information Service");
-        ssi_tree = proto_item_add_subtree(ti, ett_ssi);
-    }
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, ssi_tree, ssi_rightsinfo_tlvs);
+	}
+	return offset;
+}
 
-  switch(aiminfo->subtype)
-    {    
-	case FAMILY_SSI_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, ssi_tree);
-    case FAMILY_SSI_LIST:
-	  return dissect_aim_snac_ssi_list(tvb, pinfo, offset, ssi_tree, aiminfo->subtype);
-	case FAMILY_SSI_RIGHTSINFO:
-		while(tvb_length_remaining(tvb, offset) > 0) {
-			offset = dissect_aim_tlv(tvb, pinfo, offset, ssi_tree, ssi_rightsinfo_tlvs);
-		}
-	  return offset;
-	case FAMILY_SSI_REQRIGHTS:
-	case FAMILY_SSI_ACTIVATE:
-	case FAMILY_SSI_EDITSTART:
-	case FAMILY_SSI_EDITSTOP:
-	case FAMILY_SSI_REQLIST_FIRSTTIME:
-	  /* No data */
-	  return 0;
-	case FAMILY_SSI_ADD:
-	case FAMILY_SSI_MOD:
-	case FAMILY_SSI_DEL:
-      return dissect_ssi_item(tvb, pinfo, offset, ssi_tree, aiminfo->subtype);
-	case FAMILY_SSI_WAS_ADDED:
-	  return dissect_aim_buddyname(tvb, pinfo, offset, ssi_tree);
-	case FAMILY_SSI_REQLIST:
-	case FAMILY_SSI_SRVACK:
-	case FAMILY_SSI_NOLIST:
-	case FAMILY_SSI_GRANT_FUTURE_AUTH:
-	case FAMILY_SSI_FUTUR_AUTH_GRANTED:
-	case FAMILY_SSI_SEND_AUTH_REQ: 
-	case FAMILY_SSI_AUTH_REQ:
-	case FAMILY_SSI_SEND_AUTH_REPLY:
-	case FAMILY_SSI_AUTH_REPLY:
-		
-	  /* FIXME */
-	  return 0;
-	 
-    default:
-	  return 0;
-    }
+static int dissect_aim_ssi_was_added(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ssi_tree)
+{
+	return dissect_aim_buddyname(tvb, pinfo, 0, ssi_tree);
 }
 
 static int dissect_aim_snac_ssi_list(tvbuff_t *tvb, packet_info *pinfo _U_, 
-				      int offset, proto_tree *tree, 
-				      guint16 subtype)
+									 proto_tree *tree)
+
 {
-  proto_item *ti;
-  proto_tree *ssi_entry = NULL;
-  guint16 num_items, i;
+	int offset = 0;
+	proto_item *ti;
+	proto_tree *ssi_entry = NULL;
+	guint16 num_items, i;
 
-  /* SSI Version */
-  proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_version, tvb, offset, 1,
-		      FALSE);
-  offset += 1;
-  
-  /* Number of items */
-  proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_numitems, tvb, offset, 2,
-		      FALSE);
-  num_items = tvb_get_ntohs(tvb, offset);
-  offset += 2;
-  
-  for(i = 0; i < num_items; i++) {
-    ti = proto_tree_add_text(tree, tvb, offset, tvb_get_ntohs(tvb, offset+10)+10, "SSI Entry");
-    ssi_entry = proto_item_add_subtree(ti, ett_aim_ssi);
-    offset = dissect_ssi_item(tvb, pinfo, offset, ssi_entry, subtype);
-     }
-  proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_last_change_time, tvb, offset, 4, FALSE);
-  return offset;
+	/* SSI Version */
+	proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_version, tvb, offset, 1,
+						FALSE);
+	offset += 1;
+
+	/* Number of items */
+	proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_numitems, tvb, offset, 2,
+						FALSE);
+	num_items = tvb_get_ntohs(tvb, offset);
+	offset += 2;
+
+	for(i = 0; i < num_items; i++) {
+		ti = proto_tree_add_text(tree, tvb, offset, tvb_get_ntohs(tvb, offset+10)+10, "SSI Entry");
+		ssi_entry = proto_item_add_subtree(ti, ett_aim_ssi);
+		offset = dissect_ssi_item(tvb, pinfo, offset, ssi_entry);
+	}
+	proto_tree_add_item(tree, hf_aim_fnac_subtype_ssi_last_change_time, tvb, offset, 4, FALSE);
+	return offset;
 }
 
+static const aim_subtype aim_fnac_family_ssi[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Request Rights", NULL },
+	{ 0x0003, "Rights Info", dissect_aim_ssi_rightsinfo },
+	{ 0x0004, "Request List (first time)", NULL },
+	{ 0x0005, "Request List", NULL },
+	{ 0x0006, "List", dissect_aim_snac_ssi_list },
+	{ 0x0007, "Activate", NULL },
+	{ 0x0008, "Add Buddy", dissect_ssi_ssi_item },
+	{ 0x0009, "Modify Buddy", dissect_ssi_ssi_item },
+	{ 0x000a, "Delete Buddy", dissect_ssi_ssi_item },
+	{ 0x000e, "Server Ack", NULL },
+	{ 0x000f, "No List", NULL },
+	{ 0x0011, "Edit Start", NULL },
+	{ 0x0012, "Edit Stop", NULL },
+	{ 0x0014, "Grant Future Authorization to Buddy", NULL },
+	{ 0x0015, "Future Authorization Granted", NULL },
+	{ 0x0018, "Send Authentication Request", NULL },
+	{ 0x0019, "Authentication Request", NULL },
+	{ 0x001a, "Send Authentication Reply", NULL },
+	{ 0x001b, "Authentication Reply", NULL },
+	{ 0x001c, "Remote User Added Client To List", dissect_aim_ssi_was_added },
+	{ 0, NULL, NULL }
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_ssi(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-    { &hf_aim_fnac_subtype_ssi_version,
-      { "SSI Version", "aim.fnac.ssi.version", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_numitems,
-      { "SSI Object count", "aim.fnac.ssi.numitems", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_last_change_time,
-      { "SSI Last Change Time", "aim.fnac.ssi.last_change_time", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_buddyname_len,
-      { "SSI Buddy Name length", "aim.fnac.ssi.buddyname_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_buddyname,
-      { "Buddy Name", "aim.fnac.ssi.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_gid,
-      { "SSI Buddy Group ID", "aim.fnac.ssi.gid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_bid,
-      { "SSI Buddy ID", "aim.fnac.ssi.bid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_type,
-      { "SSI Buddy type", "aim.fnac.ssi.type", FT_UINT16, BASE_HEX, VALS(aim_fnac_family_ssi_types), 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_tlvlen,
-      { "SSI TLV Len", "aim.fnac.ssi.tlvlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_fnac_subtype_ssi_data,
-      { "SSI Buddy Data", "aim.fnac.ssi.data", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-  };
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_aim_fnac_subtype_ssi_version,
+			{ "SSI Version", "aim.fnac.ssi.version", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_numitems,
+			{ "SSI Object count", "aim.fnac.ssi.numitems", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_last_change_time,
+			{ "SSI Last Change Time", "aim.fnac.ssi.last_change_time", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_buddyname_len,
+			{ "SSI Buddy Name length", "aim.fnac.ssi.buddyname_len", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_buddyname,
+			{ "Buddy Name", "aim.fnac.ssi.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_gid,
+			{ "SSI Buddy Group ID", "aim.fnac.ssi.gid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_bid,
+			{ "SSI Buddy ID", "aim.fnac.ssi.bid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_type,
+			{ "SSI Buddy type", "aim.fnac.ssi.type", FT_UINT16, BASE_HEX, VALS(aim_fnac_family_ssi_types), 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_tlvlen,
+			{ "SSI TLV Len", "aim.fnac.ssi.tlvlen", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_fnac_subtype_ssi_data,
+			{ "SSI Buddy Data", "aim.fnac.ssi.data", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+	};
 
-/* Setup protocol subtree array */
-  static gint *ett[] = {
-    &ett_aim_ssi,
-	&ett_ssi,
-  };
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_aim_ssi,
+		&ett_ssi,
+	};
 
-/* Register the protocol name and description */
-  proto_aim_ssi = proto_register_protocol("AIM Server Side Info", "AIM SSI", "aim_ssi");
+	/* Register the protocol name and description */
+	proto_aim_ssi = proto_register_protocol("AIM Server Side Info", "AIM SSI", "aim_ssi");
 
-/* Required function calls to register the header fields and subtrees used */
-  proto_register_field_array(proto_aim_ssi, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_aim_ssi, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
 }
 
 void
 proto_reg_handoff_aim_ssi(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_ssi, proto_aim_ssi);
-  dissector_add("aim.family", FAMILY_SSI, aim_handle);
-  aim_init_family(FAMILY_SSI, "SSI", aim_fnac_family_ssi);
+	aim_init_family(proto_aim_ssi, ett_aim_ssi, FAMILY_SSI, aim_fnac_family_ssi);
 }
Index: epan/dissectors/packet-aim-messaging.c
===================================================================
--- epan/dissectors/packet-aim-messaging.c	(revision 12042)
+++ epan/dissectors/packet-aim-messaging.c	(working copy)
@@ -43,41 +43,7 @@
 
 #define FAMILY_MESSAGING  0x0004
 
-/* Family Messaging Service */
-#define FAMILY_MESSAGING_ERROR          0x0001
-#define FAMILY_MESSAGING_SETICBMPARAM   0x0002
-#define FAMILY_MESSAGING_RESETICBMPARAM 0x0003
-#define FAMILY_MESSAGING_REQPARAMINFO   0x0004
-#define FAMILY_MESSAGING_PARAMINFO      0x0005
-#define FAMILY_MESSAGING_OUTGOING       0x0006
-#define FAMILY_MESSAGING_INCOMING       0x0007
-#define FAMILY_MESSAGING_EVILREQ		0x0008
-#define FAMILY_MESSAGING_EVIL           0x0009
-#define FAMILY_MESSAGING_MISSEDCALL     0x000a
-#define FAMILY_MESSAGING_CLIENTAUTORESP 0x000b
-#define FAMILY_MESSAGING_ACK            0x000c
-#define FAMILY_MESSAGING_MINITYPING     0x0014
-#define FAMILY_MESSAGING_DEFAULT        0xffff
 
-static const value_string aim_fnac_family_messaging[] = {
-  { FAMILY_MESSAGING_ERROR, "Error" },
-  { FAMILY_MESSAGING_SETICBMPARAM, "Set ICBM Parameter" },
-  { FAMILY_MESSAGING_RESETICBMPARAM, "Reset ICBM Parameter" },
-  { FAMILY_MESSAGING_REQPARAMINFO, "Request Parameter Info" },
-  { FAMILY_MESSAGING_PARAMINFO, "Parameter Info" },
-  { FAMILY_MESSAGING_INCOMING, "Incoming" },
-  { FAMILY_MESSAGING_OUTGOING, "Outgoing" },
-  { FAMILY_MESSAGING_EVILREQ, "Evil Request" },
-  { FAMILY_MESSAGING_EVIL, "Evil Response" },
-  { FAMILY_MESSAGING_MISSEDCALL, "Missed Call" },
-  { FAMILY_MESSAGING_CLIENTAUTORESP, "Client Auto Response" },
-  { FAMILY_MESSAGING_ACK, "Acknowledge" },
-  { FAMILY_MESSAGING_MINITYPING, "Mini Typing Notifications (MTN)" },
-  { FAMILY_MESSAGING_DEFAULT, "Messaging Default" },
-  { 0, NULL }
-};
-
-
 #define INCOMING_CH1_MESSAGE_BLOCK     0x0002
 #define INCOMING_CH1_SERVER_ACK_REQ    0x0003
 #define INCOMING_CH1_MESSAGE_AUTH_RESP 0x0004
@@ -138,186 +104,190 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_messaging = -1;
 
-static int dissect_aim_messaging(tvbuff_t *tvb, packet_info *pinfo, 
-				       proto_tree *tree)
+static int dissect_aim_msg_outgoing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *msg_tree)
 {
-  guint8 buddyname_length = 0;
-  char buddyname[MAX_BUDDYNAME_LENGTH + 1];
-  int offset = 0;
-  struct aiminfo *aiminfo = pinfo->private_data;
-  proto_item *ti = NULL;
-  proto_tree *msg_tree = NULL;
-  
-  if(tree) {
-    ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Messaging Service");
-    msg_tree = proto_item_add_subtree(ti, ett_aim_messaging);
-  }
+	int offset = 0;
+	/* ICBM Cookie */
+	proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
+	offset += 8;
 
-  switch(aiminfo->subtype)
-    {    
-    case FAMILY_MESSAGING_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, msg_tree);
-    case FAMILY_MESSAGING_RESETICBMPARAM:
-    case FAMILY_MESSAGING_REQPARAMINFO:
-      /* No data */
-      return 0;
-    case FAMILY_MESSAGING_OUTGOING:
+	/* Message Channel ID */
+	proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
+						FALSE);
+	offset += 2;
 
-      /* ICBM Cookie */
-      proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
-      offset += 8;
+	/* Add the outgoing username to the info column */
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+		char buddyname[MAX_BUDDYNAME_LENGTH+1];
+		int buddyname_length = aim_get_buddyname(buddyname, tvb, offset, 
+											 offset + 1);
+		col_append_fstr(pinfo->cinfo, COL_INFO, " to: %s",
+						format_text(buddyname, buddyname_length));
+	}
 
-      /* Message Channel ID */
-      proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
-			  FALSE);
-      offset += 2;
+	offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
 
-      /* Add the outgoing username to the info column */
-      if (check_col(pinfo->cinfo, COL_INFO)) {
-	buddyname_length = aim_get_buddyname(buddyname, tvb, offset, 
-					     offset + 1);
-	col_append_fstr(pinfo->cinfo, COL_INFO, " to: %s",
-	                format_text(buddyname, buddyname_length));
-      }
+	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);
+	}
 
-      offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
+	return offset;
+}
 
-      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);
-      }
 
-      return offset;
-      
-    case FAMILY_MESSAGING_INCOMING:
+static int dissect_aim_msg_incoming(tvbuff_t *tvb, packet_info *pinfo, proto_tree *msg_tree)
+{
+	int offset = 0;
+	/* ICBM Cookie */
+	proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
+	offset += 8;
 
-      /* ICBM Cookie */
-      proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
-      offset += 8;
+	/* Message Channel ID */
+	proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
+						FALSE);
+	offset += 2;
 
-      /* Message Channel ID */
-      proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
-			  FALSE);
-      offset += 2;
+	offset = dissect_aim_userinfo(tvb, pinfo, offset, msg_tree);
 
-      offset = dissect_aim_userinfo(tvb, pinfo, offset, msg_tree);
-	  
-      while(tvb_reported_length_remaining(tvb, offset) > 0) {
-	offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree, 
-					  messaging_incoming_ch1_tlvs);
-      }
-      
-      return offset;
-    case FAMILY_MESSAGING_SETICBMPARAM:
-    case FAMILY_MESSAGING_PARAMINFO:
-      proto_tree_add_item(msg_tree, hf_aim_icbm_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      proto_tree_add_item(msg_tree, hf_aim_icbm_msg_flags, tvb, offset, 4, tvb_get_ntoh24(tvb, offset)); offset+=4;
-      proto_tree_add_item(msg_tree, hf_aim_icbm_max_snac_size, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      proto_tree_add_item(msg_tree, hf_aim_icbm_max_sender_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      proto_tree_add_item(msg_tree, hf_aim_icbm_max_receiver_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      proto_tree_add_item(msg_tree, hf_aim_icbm_min_msg_interval, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      proto_tree_add_item(msg_tree, hf_aim_icbm_unknown, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      return offset;
-    case FAMILY_MESSAGING_EVILREQ:
-      proto_tree_add_item(msg_tree, hf_aim_icbm_evil, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      return dissect_aim_buddyname(tvb, pinfo, offset, tree);
-    case FAMILY_MESSAGING_EVIL:
-      proto_tree_add_item(msg_tree, hf_aim_evil_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      proto_tree_add_item(msg_tree, hf_aim_evil_new_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      return offset;
-    case FAMILY_MESSAGING_MINITYPING:
-      proto_tree_add_item(msg_tree,hf_aim_icbm_notification_cookie, tvb, offset, 8, FALSE); offset+=8;
-      proto_tree_add_item(msg_tree,hf_aim_icbm_notification_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
-      proto_tree_add_item(msg_tree,hf_aim_icbm_notification_type, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-      return offset;
-    case FAMILY_MESSAGING_MISSEDCALL:
-    case FAMILY_MESSAGING_CLIENTAUTORESP:
-    case FAMILY_MESSAGING_ACK:
-      /*FIXME*/
+	while(tvb_reported_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree, 
+								 messaging_incoming_ch1_tlvs);
+	}
 
+	return offset;
+}
 
-    default:
-      return 0;
-    }
+static int dissect_aim_msg_params(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *msg_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_msg_flags, tvb, offset, 4, tvb_get_ntoh24(tvb, offset)); offset+=4;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_max_snac_size, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_max_sender_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_max_receiver_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_min_msg_interval, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_unknown, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	return offset;
 }
 
+static int dissect_aim_msg_evil_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *msg_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(msg_tree, hf_aim_icbm_evil, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	return dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
+}
+
+
+static int dissect_aim_msg_evil_repl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *msg_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(msg_tree, hf_aim_evil_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	proto_tree_add_item(msg_tree, hf_aim_evil_new_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	return offset;
+}
+
+static int dissect_aim_msg_minityping(tvbuff_t *tvb, packet_info *pinfo, proto_tree *msg_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(msg_tree,hf_aim_icbm_notification_cookie, tvb, offset, 8, FALSE); offset+=8;
+	proto_tree_add_item(msg_tree,hf_aim_icbm_notification_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
+	proto_tree_add_item(msg_tree,hf_aim_icbm_notification_type, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	return offset;
+}
+
+static const aim_subtype aim_fnac_family_messaging[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Set ICBM Parameter", dissect_aim_msg_params },
+	{ 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 },
+	{ 0x0008, "Evil Request", dissect_aim_msg_evil_req },
+	{ 0x0009, "Evil Response", dissect_aim_msg_evil_repl  },
+	{ 0x000a, "Missed Call", NULL },
+	{ 0x000b, "Client Auto Response", NULL },
+	{ 0x000c, "Acknowledge", NULL },
+	{ 0x0014, "Mini Typing Notifications (MTN)", dissect_aim_msg_minityping },
+	{ 0, NULL, NULL }
+};
+
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_messaging(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-    { &hf_aim_icbm_channel,
-      { "Channel to setup", "aim.icbm.channel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_msg_flags, 
-      { "Message Flags", "aim.icbm.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_max_snac_size,
-      { "Max SNAC Size", "aim.icbm.max_snac", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_max_sender_warnlevel,
-      { "Max sender warn level", "aim.icbm.max_sender_warn-level", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_max_receiver_warnlevel,
-      { "max receiver warn level", "aim.icbm.max_receiver_warnlevel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_min_msg_interval,
-      { "Minimum message interval (seconds)", "aim.icbm.min_msg_interval", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_unknown,
-      { "Unknown parameter", "aim.icbm.unknown", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_cookie,
-      { "ICBM Cookie", "aim.messaging.icbmcookie", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_message_channel_id,
-      { "Message Channel ID", "aim.messaging.channelid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_icbm_evil,
-      { "Send Evil Bit As", "aim.evilreq.origin", FT_UINT16, BASE_DEC, VALS(evil_origins), 0x0, "", HFILL },
-    },
-    { &hf_aim_evil_warn_level,
-      { "Old warning level", "aim.evil.warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_evil_new_warn_level,
-      { "New warning level", "aim.evil.new_warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_notification_cookie,
-      { "Notification Cookie", "aim.notification.cookie", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_notification_channel,
-      { "Notification Channel", "aim.notification.channel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_icbm_notification_type,
-      { "Notification Type", "aim.notification.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-  };
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_aim_icbm_channel,
+			{ "Channel to setup", "aim.icbm.channel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_msg_flags, 
+			{ "Message Flags", "aim.icbm.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_max_snac_size,
+			{ "Max SNAC Size", "aim.icbm.max_snac", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_max_sender_warnlevel,
+			{ "Max sender warn level", "aim.icbm.max_sender_warn-level", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_max_receiver_warnlevel,
+			{ "max receiver warn level", "aim.icbm.max_receiver_warnlevel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_min_msg_interval,
+			{ "Minimum message interval (seconds)", "aim.icbm.min_msg_interval", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_unknown,
+			{ "Unknown parameter", "aim.icbm.unknown", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_cookie,
+			{ "ICBM Cookie", "aim.messaging.icbmcookie", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_message_channel_id,
+			{ "Message Channel ID", "aim.messaging.channelid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_icbm_evil,
+			{ "Send Evil Bit As", "aim.evilreq.origin", FT_UINT16, BASE_DEC, VALS(evil_origins), 0x0, "", HFILL },
+		},
+		{ &hf_aim_evil_warn_level,
+			{ "Old warning level", "aim.evil.warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_evil_new_warn_level,
+			{ "New warning level", "aim.evil.new_warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_notification_cookie,
+			{ "Notification Cookie", "aim.notification.cookie", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_notification_channel,
+			{ "Notification Channel", "aim.notification.channel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_icbm_notification_type,
+			{ "Notification Type", "aim.notification.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+	};
 
-/* Setup protocol subtree array */
-  static gint *ett[] = {
-    &ett_aim_messaging,
-  };
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_aim_messaging,
+	};
 
-/* Register the protocol name and description */
-  proto_aim_messaging = proto_register_protocol("AIM Messaging", "AIM Messaging", "aim_messaging");
+	/* Register the protocol name and description */
+	proto_aim_messaging = proto_register_protocol("AIM Messaging", "AIM Messaging", "aim_messaging");
 
-/* Required function calls to register the header fields and subtrees used */
-  proto_register_field_array(proto_aim_messaging, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_aim_messaging, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
 }
 
 void
 proto_reg_handoff_aim_messaging(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_messaging, proto_aim_messaging);
-  dissector_add("aim.family", FAMILY_MESSAGING, aim_handle);
-  aim_init_family(FAMILY_MESSAGING, "Messaging", aim_fnac_family_messaging);
+	aim_init_family(proto_aim_messaging, ett_aim_messaging, FAMILY_MESSAGING, aim_fnac_family_messaging);
 }
Index: epan/dissectors/packet-aim-bos.c
===================================================================
--- epan/dissectors/packet-aim-bos.c	(revision 12042)
+++ epan/dissectors/packet-aim-bos.c	(working copy)
@@ -42,29 +42,7 @@
 #define FAMILY_BOS        0x0009
 
 /* Family BOS (Misc) */
-#define FAMILY_BOS_ERROR              0x0001
-#define FAMILY_BOS_RIGHTSQUERY        0x0002
-#define FAMILY_BOS_RIGHTS             0x0003
-#define FAMILY_BOS_SET_GROUP_PERM     0x0004
-#define FAMILY_BOS_ADD_TO_VISIBLE     0x0005
-#define FAMILY_BOS_DEL_FROM_VISIBLE   0x0006
-#define FAMILY_BOS_ADD_TO_INVISIBLE   0x0007
-#define FAMILY_BOS_DEL_FROM_INVISIBLE 0x0008
-#define FAMILY_BOS_DEFAULT            0xffff
 
-static const value_string aim_fnac_family_bos[] = {
-  { FAMILY_BOS_ERROR, "Error" },
-  { FAMILY_BOS_RIGHTSQUERY, "Rights Query" },
-  { FAMILY_BOS_RIGHTS, "Rights" },
-  { FAMILY_BOS_SET_GROUP_PERM, "Set Group Permissions Mask" },
-  { FAMILY_BOS_ADD_TO_VISIBLE, "Add To Visible List" },
-  { FAMILY_BOS_DEL_FROM_VISIBLE, "Delete From Visible List" },
-  { FAMILY_BOS_ADD_TO_INVISIBLE, "Add To Invisible List" },
-  { FAMILY_BOS_DEL_FROM_INVISIBLE, "Delete From Invisible List" },
-  { FAMILY_BOS_DEFAULT, "BOS Default" },
-  { 0, NULL }
-};
-
 #define CLASS_UNCONFIRMED 			 0x0001
 #define CLASS_ADMINISTRATOR			 0x0002
 #define CLASS_AOL				     0x0004
@@ -95,45 +73,28 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_bos      = -1;
 
-static int dissect_aim_bos(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-	struct aiminfo *aiminfo = pinfo->private_data;
+static int dissect_aim_bos_set_group_perm(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *bos_tree) 
+{
 	int offset = 0;
-	proto_item *ti;
-	proto_tree *bos_tree = NULL;
-	guint32 userclass;
+	guint32 userclass = tvb_get_ntohl(tvb, offset);
+	proto_item *ti = proto_tree_add_uint(bos_tree, hf_aim_bos_class, tvb, offset, 4, userclass); 
+	return dissect_aim_userclass(tvb, offset, 4, ti, userclass);
+}
 
-	if(tree) {
-		ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Privacy Management Service");
-		bos_tree = proto_item_add_subtree(ti, ett_aim_bos);
+static int dissect_aim_bos_rights(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bos_tree) {
+	int offset = 0;
+	while(tvb_reported_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, bos_tree, privacy_tlvs);
 	}
+	return offset;
+}
 
-	switch(aiminfo->subtype) {
-		case FAMILY_BOS_ERROR:
-			return dissect_aim_snac_error(tvb, pinfo, offset, bos_tree);
-		case FAMILY_BOS_RIGHTSQUERY:
-			/* No data */
-			return 0;
-		case FAMILY_BOS_SET_GROUP_PERM:
-			userclass = tvb_get_ntohl(tvb, offset);
-			ti = proto_tree_add_uint(bos_tree, hf_aim_bos_class, tvb, offset, 4, userclass); 
-			return dissect_aim_userclass(tvb, offset, 4, ti, userclass);
-		case FAMILY_BOS_RIGHTS:
-			while(tvb_reported_length_remaining(tvb, offset) > 0) {
-				offset = dissect_aim_tlv(tvb, pinfo, offset, bos_tree, privacy_tlvs);
-			}
-			return offset;
-		case FAMILY_BOS_ADD_TO_VISIBLE:
-		case FAMILY_BOS_DEL_FROM_VISIBLE:
-	  	case FAMILY_BOS_ADD_TO_INVISIBLE:
-	  	case FAMILY_BOS_DEL_FROM_INVISIBLE:
-			while(tvb_reported_length_remaining(tvb, offset) > 0) {
-				offset = dissect_aim_buddyname(tvb, pinfo, offset, bos_tree);
-			}
-			return offset;
-			
-		default:
-			return 0;
+static int dissect_aim_bos_buddyname(tvbuff_t *tvb, packet_info *pinfo, proto_tree *bos_tree) {
+	int offset = 0;
+	while(tvb_reported_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_buddyname(tvb, pinfo, offset, bos_tree);
 	}
+	return offset;
 }
 
 /* Register the protocol with Ethereal */
@@ -141,35 +102,43 @@
 proto_register_aim_bos(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-    { &hf_aim_bos_data,
-      { "Data", "aim.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-	{ &hf_aim_bos_class,
-	   { "User class", "aim.bos.userclass", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
-	},
-  };
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_aim_bos_data,
+			{ "Data", "aim.data", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_bos_class,
+			{ "User class", "aim.bos.userclass", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
+		},
+	};
 
-/* Setup protocol subtree array */
-  static gint *ett[] = {
-    &ett_aim_bos,
-  };
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_aim_bos,
+	};
 
-/* Register the protocol name and description */
-  proto_aim_bos = proto_register_protocol("AIM Privacy Management Service", "AIM BOS", "aim_bos");
+	/* Register the protocol name and description */
+	proto_aim_bos = proto_register_protocol("AIM Privacy Management Service", "AIM BOS", "aim_bos");
 
-/* Required function calls to register the header fields and subtrees used */
-  proto_register_field_array(proto_aim_bos, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_aim_bos, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
 }
 
+static const aim_subtype aim_fnac_family_bos[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Rights Query", NULL },
+	{ 0x0003, "Rights" , dissect_aim_bos_rights },
+	{ 0x0004, "Set Group Permissions Mask", dissect_aim_bos_set_group_perm },
+	{ 0x0005, "Add To Visible List", dissect_aim_bos_buddyname },
+	{ 0x0006, "Delete From Visible List", dissect_aim_bos_buddyname },
+	{ 0x0007, "Add To Invisible List", dissect_aim_bos_buddyname },
+	{ 0x0008, "Delete From Invisible List", dissect_aim_bos_buddyname },
+	{ 0, NULL, NULL }
+};
+
 void
 proto_reg_handoff_aim_bos(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_bos, proto_aim_bos);
-  dissector_add("aim.family", FAMILY_BOS, aim_handle);
-  aim_init_family(FAMILY_BOS, "Privacy Management Service", aim_fnac_family_bos);
+	aim_init_family(proto_aim_bos, ett_aim_bos, FAMILY_BOS, aim_fnac_family_bos);
 }
Index: epan/dissectors/packet-aim-adverts.c
===================================================================
--- epan/dissectors/packet-aim-adverts.c	(revision 12042)
+++ epan/dissectors/packet-aim-adverts.c	(working copy)
@@ -41,52 +41,23 @@
 
 #define FAMILY_ADVERTS    0x0005
 
-/* Family Advertising */
-#define FAMILY_ADVERTS_ERROR          0x0001
-#define FAMILY_ADVERTS_REQUEST        0x0002
-#define FAMILY_ADVERTS_DATA           0x0003
-#define FAMILY_ADVERTS_DEFAULT        0xffff
-
-static const value_string aim_fnac_family_adverts[] = {
-  { FAMILY_ADVERTS_ERROR, "Error" },
-  { FAMILY_ADVERTS_REQUEST, "Request" },
-  { FAMILY_ADVERTS_DATA, "Data (GIF)" },
-  { FAMILY_ADVERTS_DEFAULT, "Adverts Default" },
-  { 0, NULL }
+static const aim_subtype aim_fnac_family_adverts[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Request", NULL },
+	/* FIXME: */
+	/* From other sources, I understand this response contains 
+	 * a GIF file, haven't actually seen one though. And this
+	 * family appears to be deprecated, so we might never find out.. */
+  { 0x0003, "Data (GIF)", NULL },
+  { 0, NULL, NULL }
 };
 
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_adverts = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_adverts      = -1;
 
-static int dissect_aim_adverts(tvbuff_t *tvb _U_, 
-				     packet_info *pinfo _U_, 
-				     proto_tree *tree _U_)
-{
-	struct aiminfo *aiminfo = pinfo->private_data;
-	int offset = 0;
-
-	switch(aiminfo->subtype) {
-		case FAMILY_ADVERTS_ERROR:
-		return dissect_aim_snac_error(tvb, pinfo, offset, tree);
-		break;
-		case FAMILY_ADVERTS_REQUEST:
-			/* FIXME */
-		return 0;
-		case FAMILY_ADVERTS_DATA:
-			/* FIXME: */
-			/* From other sources, I understand this response contains 
-			 * a GIF file, haven't actually seen one though. And this
-			 * family appears to be deprecated, so we might never find out.. */
-		return 0;
-	}
-
-	return 0;
-}
-
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_adverts(void)
@@ -114,8 +85,5 @@
 void
 proto_reg_handoff_aim_adverts(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_adverts, proto_aim_adverts);
-  dissector_add("aim.family", FAMILY_ADVERTS, aim_handle);
-  aim_init_family(FAMILY_ADVERTS, "Advertisements", aim_fnac_family_adverts);
+  aim_init_family(proto_aim_adverts, ett_aim_adverts, FAMILY_ADVERTS, aim_fnac_family_adverts);
 }
Index: epan/dissectors/packet-aim-admin.c
===================================================================
--- epan/dissectors/packet-aim-admin.c	(revision 12042)
+++ epan/dissectors/packet-aim-admin.c	(working copy)
@@ -41,28 +41,6 @@
 
 #define FAMILY_ADMIN      0x0007
 
-/* Family Admin */
-#define FAMILY_ADMIN_ERROR            0x0001
-#define FAMILY_ADMIN_ACCNT_INFO_REQ   0x0002
-#define FAMILY_ADMIN_ACCNT_INFO_REPL  0x0003
-#define FAMILY_ADMIN_INFOCHANGEREQ    0x0004
-#define FAMILY_ADMIN_INFOCHANGEREPLY  0x0005
-#define FAMILY_ADMIN_ACCT_CFRM_REQ    0x0006
-#define FAMILY_ADMIN_ACCT_CFRM_REPL   0x0007
-#define FAMILY_ADMIN_DEFAULT          0xffff
-
-static const value_string aim_fnac_family_admin[] = {
-  { FAMILY_ADMIN_ERROR, "Error" },
-  { FAMILY_ADMIN_ACCNT_INFO_REQ, "Request Account Information" },
-  { FAMILY_ADMIN_ACCNT_INFO_REPL, "Requested Account Information" },
-  { FAMILY_ADMIN_INFOCHANGEREQ, "Infochange Request" },
-  { FAMILY_ADMIN_INFOCHANGEREPLY, "Infochange Reply" },
-  { FAMILY_ADMIN_ACCT_CFRM_REQ, "Account Confirm Request" },
-  { FAMILY_ADMIN_ACCT_CFRM_REPL, "Account Confirm Reply" },
-  { FAMILY_ADMIN_DEFAULT, "Adminstrative Default" },
-  { 0, NULL }
-};
-
 #define CONFIRM_STATUS_EMAIL_SENT 		 0x00
 #define CONFIRM_STATUS_ALREADY_CONFIRMED 0x1E
 #define CONFIRM_STATUS_SERVER_ERROR	     0x23
@@ -83,51 +61,50 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_admin          = -1;
 
-static int dissect_aim_admin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
-	struct aiminfo *aiminfo = pinfo->private_data;
-    proto_item *ti = NULL;
-    proto_tree *admin_tree = NULL;
+static int dissect_aim_admin_accnt_info_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *admin_tree) 
+{
+	proto_tree_add_item(admin_tree, hf_admin_acctinfo_code, tvb, 0, 2, tvb_get_ntohs(tvb, 0)); 
+	proto_tree_add_text(admin_tree, tvb, 2, 2, "Unknown");
+	return 4;
+}
+
+static int dissect_aim_admin_accnt_info_repl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *admin_tree) 
+{
 	int offset = 0;
-                                                                                
-    if(tree) {
-        ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Administration Service");
-        admin_tree = proto_item_add_subtree(ti, ett_aim_admin);
-    }
-	
-	switch(aiminfo->subtype) {
-	case FAMILY_ADMIN_ERROR:
-		return dissect_aim_snac_error(tvb, pinfo, 0, admin_tree);
-	case FAMILY_ADMIN_ACCNT_INFO_REQ:
-		proto_tree_add_item(admin_tree, hf_admin_acctinfo_code, tvb, 0, 2, tvb_get_ntohs(tvb, 0)); 
-		proto_tree_add_text(admin_tree, tvb, 2, 2, "Unknown");
-		return 4;
-		
-	case FAMILY_ADMIN_INFOCHANGEREPLY:
-    case FAMILY_ADMIN_ACCNT_INFO_REPL:
-		{
-			proto_tree_add_uint(admin_tree, hf_admin_acctinfo_permissions, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-			return dissect_aim_tlv_list(tvb, pinfo, offset, admin_tree, client_tlvs);
-		}
-	case FAMILY_ADMIN_INFOCHANGEREQ:
-		while(tvb_length_remaining(tvb, offset) > 0) {
-			offset = dissect_aim_tlv(tvb, pinfo, offset, admin_tree, client_tlvs);
-		}
-		return offset;
-	case FAMILY_ADMIN_ACCT_CFRM_REQ:
-		/* No data */
-		return 0;
-	case FAMILY_ADMIN_ACCT_CFRM_REPL:
-		proto_tree_add_uint(admin_tree, hf_admin_confirm_status, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
-		while(tvb_length_remaining(tvb, offset) > 0) {
-			offset = dissect_aim_tlv(tvb, pinfo, offset, admin_tree, client_tlvs);
-		}
-		return offset;
+	proto_tree_add_uint(admin_tree, hf_admin_acctinfo_permissions, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	return dissect_aim_tlv_list(tvb, pinfo, offset, admin_tree, client_tlvs);
+}
 
-	default: return 0;
+static int dissect_aim_admin_info_change_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *admin_tree) 
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, admin_tree, client_tlvs);
 	}
-	return 0;
+	return offset;
 }
 
+static int dissect_aim_admin_cfrm_repl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *admin_tree) 
+{
+	int offset = 0;	
+	proto_tree_add_uint(admin_tree, hf_admin_confirm_status, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, admin_tree, client_tlvs);
+	}
+	return offset;
+}
+
+static const aim_subtype aim_fnac_family_admin[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Request Account Information", dissect_aim_admin_accnt_info_req },
+  { 0x0003, "Requested Account Information", dissect_aim_admin_accnt_info_repl },
+  { 0x0004, "Infochange Request", dissect_aim_admin_info_change_req },
+  { 0x0005, "Infochange Reply", dissect_aim_admin_accnt_info_repl },
+  { 0x0006, "Account Confirm Request", NULL },
+  { 0x0007, "Account Confirm Reply", dissect_aim_admin_cfrm_repl},
+  { 0, NULL, NULL }
+};
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_admin(void)
@@ -162,9 +139,5 @@
 void
 proto_reg_handoff_aim_admin(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_admin, proto_aim_admin);
-  dissector_add("aim.family", FAMILY_ADMIN, aim_handle);
-  aim_init_family(FAMILY_ADMIN, "Administration", aim_fnac_family_admin);
+  aim_init_family(proto_aim_admin, ett_aim_admin, FAMILY_ADMIN, aim_fnac_family_admin);
 }
Index: epan/dissectors/packet-aim-userlookup.c
===================================================================
--- epan/dissectors/packet-aim-userlookup.c	(revision 12042)
+++ epan/dissectors/packet-aim-userlookup.c	(working copy)
@@ -41,20 +41,6 @@
 
 #define FAMILY_USERLOOKUP 0x000A
 
-/* Family User Lookup */
-#define FAMILY_USERLOOKUP_ERROR        0x0001
-#define FAMILY_USERLOOKUP_SEARCHEMAIL  0x0002
-#define FAMILY_USERLOOKUP_SEARCHRESULT 0x0003
-#define FAMILY_USERLOOKUP_DEFAULT      0xffff
-
-static const value_string aim_fnac_family_userlookup[] = {
-  { FAMILY_USERLOOKUP_ERROR, "Error" },
-  { FAMILY_USERLOOKUP_SEARCHEMAIL, "Search for user by email address" },
-  { FAMILY_USERLOOKUP_SEARCHRESULT, "Search results" },
-  { FAMILY_USERLOOKUP_DEFAULT, "Userlookup Default" },
-  { 0, NULL }
-};
-
 /* Initialize the protocol and registered fields */
 static int hf_aim_userlookup_email = -1;
 static int proto_aim_userlookup = -1;
@@ -62,37 +48,29 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_userlookup = -1;
 
-static int dissect_aim_snac_userlookup(tvbuff_t *tvb _U_, packet_info *pinfo, 
-					proto_tree *tree _U_)
+static int dissect_aim_userlookup_search(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *lookup_tree)
 {
-	struct aiminfo *aiminfo = pinfo->private_data;
-	int offset = 0;
-	
-    proto_item *ti = NULL;
-    proto_tree *lookup_tree = NULL;
-                                                                                
-    if(tree) {
-        ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Lookup Service");
-		lookup_tree = proto_item_add_subtree(ti, ett_aim_userlookup);
-    }
-
-
-	switch(aiminfo->subtype) {
-	case FAMILY_USERLOOKUP_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, tree);
-	case FAMILY_USERLOOKUP_SEARCHEMAIL:
 	  proto_tree_add_item(lookup_tree, hf_aim_userlookup_email, tvb, 0, tvb_length(tvb), FALSE);
 	  return tvb_length(tvb);
-	case FAMILY_USERLOOKUP_SEARCHRESULT:
-        while(tvb_length_remaining(tvb, offset) > 0) {
-            offset = dissect_aim_tlv(tvb, pinfo, offset, lookup_tree, client_tlvs);
-        }
-		return offset;
-	}
+}
 
-	return 0;
+
+static int dissect_aim_userlookup_result(tvbuff_t *tvb, packet_info *pinfo, proto_tree *lookup_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+    	offset = dissect_aim_tlv(tvb, pinfo, offset, lookup_tree, client_tlvs);
+    }
+	return offset;
 }
 
+static const aim_subtype aim_fnac_family_userlookup[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Search for user by email address", dissect_aim_userlookup_search },
+  { 0x0003, "Search results", dissect_aim_userlookup_result },
+  { 0, NULL, NULL }
+};
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_userlookup(void)
@@ -120,8 +98,5 @@
 void
 proto_reg_handoff_aim_userlookup(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_userlookup, proto_aim_userlookup);
-  dissector_add("aim.family", FAMILY_USERLOOKUP, aim_handle);
-  aim_init_family(FAMILY_USERLOOKUP, "User Lookup", aim_fnac_family_userlookup);
+  aim_init_family(proto_aim_userlookup, ett_aim_userlookup, FAMILY_USERLOOKUP, aim_fnac_family_userlookup);
 }
Index: epan/dissectors/packet-aim-generic.c
===================================================================
--- epan/dissectors/packet-aim-generic.c	(revision 12042)
+++ epan/dissectors/packet-aim-generic.c	(working copy)
@@ -45,68 +45,7 @@
 /* SNAC families */
 #define FAMILY_GENERIC    0x0001
 
-/* Family Generic */
-#define FAMILY_GENERIC_ERROR          0x0001
-#define FAMILY_GENERIC_CLIENTREADY    0x0002
-#define FAMILY_GENERIC_SERVERREADY    0x0003
-#define FAMILY_GENERIC_SERVICEREQ     0x0004
-#define FAMILY_GENERIC_REDIRECT       0x0005
-#define FAMILY_GENERIC_RATEINFOREQ    0x0006
-#define FAMILY_GENERIC_RATEINFO       0x0007
-#define FAMILY_GENERIC_RATEINFOACK    0x0008
-#define FAMILY_GENERIC_RATECHANGE     0x000a
-#define FAMILY_GENERIC_SERVERPAUSE    0x000b
-#define FAMILY_GENERIC_CLIENTPAUSEACK 0x000c
-#define FAMILY_GENERIC_SERVERRESUME   0x000d
-#define FAMILY_GENERIC_REQSELFINFO    0x000e
-#define FAMILY_GENERIC_SELFINFO       0x000f
-#define FAMILY_GENERIC_EVIL           0x0010
-#define FAMILY_GENERIC_SETIDLE        0x0011
-#define FAMILY_GENERIC_MIGRATIONREQ   0x0012
-#define FAMILY_GENERIC_MOTD           0x0013
-#define FAMILY_GENERIC_SETPRIVFLAGS   0x0014
-#define FAMILY_GENERIC_WELLKNOWNURL   0x0015
-#define FAMILY_GENERIC_NOP            0x0016
-#define FAMILY_GENERIC_CAPABILITIES   0x0017
-#define FAMILY_GENERIC_CAPACK         0x0018
-#define FAMILY_GENERIC_SETSTATUS      0x001e
-#define FAMILY_GENERIC_CLIENTVERREQ   0x001f
-#define FAMILY_GENERIC_CLIENTVERREPL  0x0020
-#define FAMILY_GENERIC_EXT_STATUS_REP 0x0021
-#define FAMILY_GENERIC_DEFAULT        0xffff
 
-static const value_string aim_fnac_family_generic[] = {
-  { FAMILY_GENERIC_ERROR, "Error" },
-  { FAMILY_GENERIC_CLIENTREADY , "Client Ready" },
-  { FAMILY_GENERIC_SERVERREADY, "Server Ready" },
-  { FAMILY_GENERIC_SERVICEREQ, "Service Request" },
-  { FAMILY_GENERIC_REDIRECT, "Redirect" },
-  { FAMILY_GENERIC_RATEINFOREQ, "Rate Info Request" },
-  { FAMILY_GENERIC_RATEINFO, "Rate Info" },
-  { FAMILY_GENERIC_RATEINFOACK, "Rate Info Ack" },
-  { FAMILY_GENERIC_RATECHANGE, "Rate Change" },
-  { FAMILY_GENERIC_SERVERPAUSE, "Server Pause" },
-  { FAMILY_GENERIC_CLIENTPAUSEACK, "Client Pause Ack" },
-  { FAMILY_GENERIC_SERVERRESUME, "Server Resume" },
-  { FAMILY_GENERIC_REQSELFINFO, "Self Info Request" },
-  { FAMILY_GENERIC_SELFINFO, "Self Info" },
-  { FAMILY_GENERIC_EVIL, "Evil" },
-  { FAMILY_GENERIC_SETIDLE, "Set Idle" },
-  { FAMILY_GENERIC_MIGRATIONREQ, "Migration Request" },
-  { FAMILY_GENERIC_MOTD, "Message Of The Day" },
-  { FAMILY_GENERIC_SETPRIVFLAGS, "Set Privilege Flags" },
-  { FAMILY_GENERIC_WELLKNOWNURL, "Well Known URL" },
-  { FAMILY_GENERIC_NOP, "noop" },
-  { FAMILY_GENERIC_CAPABILITIES, "Capabilities" },
-  { FAMILY_GENERIC_CAPACK, "Capabilities Ack" },
-  { FAMILY_GENERIC_SETSTATUS, "Set Status (ICQ specific)" },
-  { FAMILY_GENERIC_CLIENTVERREQ, "Client Verification Requst" },
-  { FAMILY_GENERIC_CLIENTVERREPL, "Client Verification Reply" },
-  { FAMILY_GENERIC_EXT_STATUS_REP, "Extended Status Reply" },
-  { FAMILY_GENERIC_DEFAULT, "Generic Default" },
-  { 0, NULL }
-};
-
 #define FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE       0x0001
 #define FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE       0x0002
 #define FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN      0x0003
@@ -167,9 +106,6 @@
 	{ 0, NULL },
 };
 
-static int dissect_aim_snac_generic(tvbuff_t *tvb, packet_info *pinfo, 
-				     proto_tree *tree);
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_generic = -1;
 static int hf_generic_motd_motdtype = -1;
@@ -216,7 +152,8 @@
 static gint ett_generic_rateinfo_group = -1;
 
 static int dissect_rate_class(tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
-					proto_tree *class_tree) {
+							  proto_tree *class_tree) 
+{
 	proto_tree_add_uint(class_tree, hf_generic_rateinfo_classid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));offset+=2;
 	proto_tree_add_uint(class_tree, hf_generic_rateinfo_windowsize, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
 	proto_tree_add_uint(class_tree, hf_generic_rateinfo_clearlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
@@ -231,13 +168,14 @@
 }
 
 static int dissect_generic_rateinfo(tvbuff_t *tvb, packet_info *pinfo _U_, 
-				    proto_tree *tree) {
+									proto_tree *tree) 
+{
 	int offset = 0;
 	guint16 i;
 	proto_item *ti;
 	guint16 numclasses = tvb_get_ntohs(tvb, 0);	
 	proto_tree *classes_tree = NULL, *groups_tree, *group_tree;
-    proto_tree_add_uint(tree, hf_generic_rateinfo_numclasses, tvb, 0, 2, numclasses );
+	proto_tree_add_uint(tree, hf_generic_rateinfo_numclasses, tvb, 0, 2, numclasses );
 	offset+=2;
 
 	if(tree) {
@@ -266,226 +204,293 @@
 		numpairs = tvb_get_ntohs(tvb, offset);
 		proto_tree_add_uint(group_tree, hf_generic_rateinfo_numpairs, tvb, offset, 2, numpairs); offset+=2;
 		for(j = 0; j < numpairs; j++) {
-			const char *fam_name, *subtype_name;
-			guint16 family; 
-			guint16 subtype;
-			family = tvb_get_ntohs(tvb, offset); offset+=2;
-			subtype = tvb_get_ntohs(tvb, offset); offset+=2;
+			guint16 family_id; 
+			guint16 subtype_id;
+			const aim_family *family;
+			const aim_subtype *subtype;
+			family_id = tvb_get_ntohs(tvb, offset); offset+=2;
+			subtype_id = tvb_get_ntohs(tvb, offset); offset+=2;
 
-			fam_name = aim_get_familyname(family);
-			subtype_name = aim_get_subtypename(family, subtype);
+			family = aim_get_family(family_id);
+			subtype = aim_get_subtype(family_id, subtype_id);
 
-			proto_tree_add_text(group_tree, tvb, offset-4, 4, "Family: %s (0x%04x), Subtype: %s (0x%04x)", fam_name?fam_name:"Unknown", family, subtype_name?subtype_name:"Unknown", subtype);
+			proto_tree_add_text(group_tree, tvb, offset-4, 4, "Family: %s (0x%04x), Subtype: %s (0x%04x)", family?family->name:"Unknown", family_id, subtype?subtype->name:"Unknown", subtype_id);
 		}
 	}
-	
+
 	return offset;
 }
 
-static int dissect_aim_snac_generic(tvbuff_t *tvb, packet_info *pinfo, 
-				    proto_tree *tree)
+static int dissect_aim_generic_clientready(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
 {
 	int offset = 0;
-	const char *name;
-	struct aiminfo *aiminfo = pinfo->private_data;
-	guint16 n, i;
-  	proto_item *ti = NULL;
-	proto_tree *gen_tree = NULL;
-	proto_tree *entry = NULL;
+	proto_item *ti = proto_tree_add_text(gen_tree, tvb, 0, tvb_length_remaining(tvb, 0), "Supported services");
+	proto_tree *entry = proto_item_add_subtree(ti, ett_generic_clientready);
 
-	if(tree) {
-		ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Generic Service");
-		gen_tree = proto_item_add_subtree(ti, ett_generic);
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		guint16 famnum = tvb_get_ntohs(tvb, offset);
+		const aim_family *family = aim_get_family(famnum);
+
+		proto_tree *subentry;
+		ti = proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", family?family->name:"Unknown Family", famnum);
+		offset+=2;
+
+		subentry = proto_item_add_subtree(ti, ett_generic_clientready_item);
+
+		proto_tree_add_text(subentry, tvb, offset, 2, "Version: %d", tvb_get_ntohs(tvb, offset) ); offset += 2;
+		proto_tree_add_text(subentry, tvb, offset, 4, "DLL Version: %u", tvb_get_ntoh24(tvb, offset) ); offset += 4;
 	}
+	return offset;
+}
+
+
+static int dissect_aim_generic_serverready(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_item *ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Supported services");
+	proto_tree *entry = proto_item_add_subtree(ti, ett_generic_clientready);
 	
-	if ((name = match_strval(aiminfo->subtype, aim_fnac_family_generic)) != NULL) {
-	  if (ti) proto_item_append_text(ti, ", %s", name);
-
-      if (check_col(pinfo->cinfo, COL_INFO)) col_add_fstr(pinfo->cinfo, COL_INFO, name);
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		guint16 famnum = tvb_get_ntohs(tvb, offset);
+		const aim_family *family = aim_get_family(famnum);
+		proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", family?family->name:"Unknown Family", famnum);
+		offset+=2;
 	}
+	return offset;
+}
 
-  switch(aiminfo->subtype)
-    {
-	case FAMILY_GENERIC_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, 0, gen_tree);
-	case FAMILY_GENERIC_CLIENTREADY:
-	   ti = proto_tree_add_text(gen_tree, tvb, 0, tvb_length_remaining(tvb, 0), "Supported services");
-	   entry = proto_item_add_subtree(ti, ett_generic_clientready);
-	   while(tvb_length_remaining(tvb, offset) > 0) {
-			guint16 famnum = tvb_get_ntohs(tvb, offset);
-			const char *famname = aim_get_familyname(famnum);
-			proto_tree *subentry;
-			ti = proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", famname?famname:"Unknown Family", famnum);
-			offset+=2;
-			
-			subentry = proto_item_add_subtree(ti, ett_generic_clientready_item);
 
-			proto_tree_add_text(subentry, tvb, offset, 2, "Version: %d", tvb_get_ntohs(tvb, offset) ); offset += 2;
-			proto_tree_add_text(subentry, tvb, offset, 4, "DLL Version: %u", tvb_get_ntoh24(tvb, offset) ); offset += 4;
-	  }
-	  return offset;
-	case FAMILY_GENERIC_SERVERREADY:
-	   ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Supported services");
-	   entry = proto_item_add_subtree(ti, ett_generic_clientready);
-	   while(tvb_length_remaining(tvb, offset) > 0) {
-			guint16 famnum = tvb_get_ntohs(tvb, offset);
-			const char *famname = aim_get_familyname(famnum);
-			proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", famname?famname:"Unknown Family", famnum);
-			offset+=2;
-	  }
-	  return offset;
-	case FAMILY_GENERIC_SERVICEREQ:
-	  name = aim_get_familyname( tvb_get_ntohs(tvb, offset) );
-      proto_tree_add_uint_format(gen_tree, hf_generic_servicereq_service, tvb, offset, 2, tvb_get_ntohs(tvb, offset), "%s (0x%04x)", name?name:"Unknown", tvb_get_ntohs(tvb, offset) );
-	  offset+=2;
-	  return offset;
-	case FAMILY_GENERIC_REDIRECT:
-	  while(tvb_length_remaining(tvb, offset) > 0) {
+static int dissect_aim_generic_service_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	const aim_family *family = aim_get_family( tvb_get_ntohs(tvb, offset) );
+
+	proto_tree_add_uint_format(gen_tree, hf_generic_servicereq_service, tvb, offset, 2, tvb_get_ntohs(tvb, offset), "%s (0x%04x)", family?family->name:"Unknown", tvb_get_ntohs(tvb, offset) );
+	offset+=2;
+	return offset;
+}
+
+static int dissect_aim_generic_redirect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
 		offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, client_tlvs);
-	  }
-	  return offset;
-	case FAMILY_GENERIC_CAPABILITIES:
-	   ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Requested services");
-	   entry = proto_item_add_subtree(ti, ett_generic_clientready);
-	   while(tvb_length_remaining(tvb, offset) > 0) {
-			guint16 famnum = tvb_get_ntohs(tvb, offset);
-			const char *famname = aim_get_familyname(famnum);
-			ti = proto_tree_add_text(entry, tvb, offset, 4, "%s (0x%x), Version: %d", famname?famname:"Unknown Family", famnum, tvb_get_ntohs(tvb, offset+2));
-			offset += 4;
-	  }
-	  return offset;
-	case FAMILY_GENERIC_CAPACK:
-	   ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Accepted requested services");
-	   entry = proto_item_add_subtree(ti, ett_generic_clientready);
-	   while(tvb_length_remaining(tvb, offset) > 0) {
-			guint16 famnum = tvb_get_ntohs(tvb, offset);
-			const char *famname = aim_get_familyname(famnum);
-			ti = proto_tree_add_text(entry, tvb, offset, 4, "%s (0x%x), Version: %d", famname?famname:"Unknown Family", famnum, tvb_get_ntohs(tvb, offset+2));
-			offset += 4;
-	  }
-	   return offset;
+	}
+	return offset;
+}
 
+static int dissect_aim_generic_capabilities(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_item *ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Requested services");
+	proto_tree *entry = proto_item_add_subtree(ti, ett_generic_clientready);
 
-    case FAMILY_GENERIC_MOTD: 
-      proto_tree_add_item(gen_tree, hf_generic_motd_motdtype, tvb, offset, 
-			  2, tvb_get_ntohs(tvb, offset));
-	  offset+=2;
-	  while(tvb_length_remaining(tvb, offset) > 0) {
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		guint16 famnum = tvb_get_ntohs(tvb, offset);
+		const aim_family *family = aim_get_family(famnum);
+		ti = proto_tree_add_text(entry, tvb, offset, 4, "%s (0x%x), Version: %d", family?family->name:"Unknown Family", famnum, tvb_get_ntohs(tvb, offset+2));
+		offset += 4;
+	}
+	return offset;
+}
+
+static int dissect_aim_generic_capack(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_item *ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Accepted requested services");
+	proto_tree *entry = proto_item_add_subtree(ti, ett_generic_clientready);
+
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		guint16 famnum = tvb_get_ntohs(tvb, offset);
+		const aim_family *family = aim_get_family(famnum);
+		ti = proto_tree_add_text(entry, tvb, offset, 4, "%s (0x%x), Version: %d", family?family->name:"Unknown Family", famnum, tvb_get_ntohs(tvb, offset+2));
+		offset += 4;
+	}
+	return offset;
+}
+
+static int dissect_aim_generic_motd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(gen_tree, hf_generic_motd_motdtype, tvb, offset, 
+						2, tvb_get_ntohs(tvb, offset));
+	offset+=2;
+	while(tvb_length_remaining(tvb, offset) > 0) {
 		offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, motd_tlvs);
-	  }
-	  return offset;
+	}
+	return offset;
+}
 
-	case FAMILY_GENERIC_RATEINFO:
-	  return dissect_generic_rateinfo(tvb, pinfo, gen_tree);
-	case FAMILY_GENERIC_RATEINFOACK:
-	  while(tvb_length_remaining(tvb, offset) > 0) {
-		  proto_tree_add_uint(gen_tree, hf_generic_rateinfoack_group, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
-		  offset+=2;
-	  }
-	  return offset;
-	case FAMILY_GENERIC_RATECHANGE:
-	  proto_tree_add_uint(gen_tree, hf_generic_ratechange_msg, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
-	  offset+=2;
-	  offset = dissect_rate_class(tvb, pinfo, offset, gen_tree);
-	  break;
-	  
+static int dissect_aim_generic_rateinfoack(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		proto_tree_add_uint(gen_tree, hf_generic_rateinfoack_group, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+		offset+=2;
+	}
+	return offset;
+}
 
-	case FAMILY_GENERIC_CLIENTPAUSEACK:
-	   while(tvb_length_remaining(tvb, offset) > 0) {
-			guint16 famnum = tvb_get_ntohs(tvb, offset);
-			const char *famname = aim_get_familyname(famnum);
-			proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", famname?famname:"Unknown Family", famnum);
-			offset += 2;
-	  }
-	  return offset;
-	case FAMILY_GENERIC_SERVERRESUME:
-	case FAMILY_GENERIC_REQSELFINFO:
-	case FAMILY_GENERIC_NOP:
-	case FAMILY_GENERIC_SERVERPAUSE:
-	case FAMILY_GENERIC_RATEINFOREQ:
-	  /* No data */
-	  return offset;
-	case FAMILY_GENERIC_MIGRATIONREQ:
-	  n = tvb_get_ntohs(tvb, offset);offset+=2;
-	  proto_tree_add_uint(gen_tree, hf_generic_migration_numfams, tvb, offset, 2, n);
-	  ti = proto_tree_add_text(gen_tree, tvb, offset, 2 * n, "Families to migrate");
-	  entry = proto_item_add_subtree(ti, ett_generic_migratefamilies);
-	  for(i = 0; i < n; i++) {
-			guint16 famnum = tvb_get_ntohs(tvb, offset);
-			const char *famname = aim_get_familyname(famnum);
-			proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", famname?famname:"Unknown Family", famnum);
-			offset += 2;
-	  }
+static int dissect_aim_generic_ratechange(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_tree_add_uint(gen_tree, hf_generic_ratechange_msg, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
+	offset+=2;
+	offset = dissect_rate_class(tvb, pinfo, offset, gen_tree);
+	return offset;
+}
 
-	  while(tvb_length_remaining(tvb, offset) > 0) {
+
+static int dissect_aim_generic_clientpauseack(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		guint16 famnum = tvb_get_ntohs(tvb, offset);
+		const aim_family *family = aim_get_family(famnum);
+		proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", family?family->name:"Unknown Family", famnum);
+		offset += 2;
+	}
+	return offset;
+}
+
+static int dissect_aim_generic_migration_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = 0;
+	guint32 n, i;
+	proto_item *ti;
+	proto_tree *entry;
+
+	n = tvb_get_ntohs(tvb, offset);offset+=2;
+	proto_tree_add_uint(gen_tree, hf_generic_migration_numfams, tvb, offset, 2, n);
+	ti = proto_tree_add_text(gen_tree, tvb, offset, 2 * n, "Families to migrate");
+	entry = proto_item_add_subtree(ti, ett_generic_migratefamilies);
+	for(i = 0; i < n; i++) {
+		guint16 famnum = tvb_get_ntohs(tvb, offset);
+		const aim_family *family = aim_get_family(famnum);
+		proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", family?family->name:"Unknown Family", famnum);
+		offset += 2;
+	}
+
+	while(tvb_length_remaining(tvb, offset) > 0) {
 		offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, client_tlvs);
-	  }
+	}
 
-	  return offset;
-	case FAMILY_GENERIC_SETPRIVFLAGS:
-	  {
-		  guint32 flags = tvb_get_ntoh24(tvb, offset); 
-		  ti = proto_tree_add_uint(gen_tree, hf_generic_priv_flags, tvb, offset, 4, flags);
-		  entry = proto_item_add_subtree(ti, ett_generic_priv_flags);
-		  proto_tree_add_boolean(entry, hf_generic_allow_idle_see, tvb, offset, 4, flags);
-		  proto_tree_add_boolean(entry, hf_generic_allow_member_see, tvb, offset, 4, flags);
-		  offset+=4;
-	  }
-	  return offset;
-	case FAMILY_GENERIC_SELFINFO:
-	  offset = dissect_aim_buddyname(tvb, pinfo, offset, gen_tree);
-	  proto_tree_add_item(gen_tree, hf_generic_selfinfo_warninglevel, tvb, offset, 2, FALSE);
-	  offset += 2;
-	  return dissect_aim_tlv_list(tvb, pinfo, offset, gen_tree, onlinebuddy_tlvs);
-	case FAMILY_GENERIC_EVIL:
-	  proto_tree_add_item(gen_tree, hf_generic_evil_new_warn_level, tvb, offset, 2, FALSE);
-	  while(tvb_length_remaining(tvb, offset)) {
+	return offset;
+}
+
+static int dissect_aim_generic_setprivflags(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	guint32 flags = tvb_get_ntoh24(tvb, offset); 
+	proto_item *ti = proto_tree_add_uint(gen_tree, hf_generic_priv_flags, tvb, offset, 4, flags);
+	proto_tree *entry = proto_item_add_subtree(ti, ett_generic_priv_flags);
+	proto_tree_add_boolean(entry, hf_generic_allow_idle_see, tvb, offset, 4, flags);
+	proto_tree_add_boolean(entry, hf_generic_allow_member_see, tvb, offset, 4, flags);
+	offset+=4;
+	return offset;
+}
+
+static int dissect_aim_generic_selfinfo_repl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = dissect_aim_buddyname(tvb, pinfo, 0, gen_tree);
+	proto_tree_add_item(gen_tree, hf_generic_selfinfo_warninglevel, tvb, offset, 2, FALSE);
+	offset += 2;
+	return dissect_aim_tlv_list(tvb, pinfo, offset, gen_tree, onlinebuddy_tlvs);
+}
+
+static int dissect_aim_generic_evil(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(gen_tree, hf_generic_evil_new_warn_level, tvb, offset, 2, FALSE);
+	while(tvb_length_remaining(tvb, offset)) {
 		offset = dissect_aim_userinfo(tvb, pinfo, offset, gen_tree);
-	  }
-	  return offset;
-	case FAMILY_GENERIC_SETIDLE:
-	  proto_tree_add_item(gen_tree, hf_generic_idle_time, tvb, offset, 2, FALSE);
-	  return 4;
-	case FAMILY_GENERIC_SETSTATUS:
-	  while(tvb_length_remaining(tvb, offset) > 0) {
+	}
+	return offset;
+}
+
+static int dissect_aim_generic_setidle(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	proto_tree_add_item(gen_tree, hf_generic_idle_time, tvb, 0, 2, FALSE);
+	return 2;
+}
+
+static int dissect_aim_generic_ext_status_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *gen_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
 		offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree, onlinebuddy_tlvs);
-	  }
-	  return offset;
-	case FAMILY_GENERIC_CLIENTVERREQ:
-	  proto_tree_add_item(gen_tree, hf_generic_client_ver_req_offset, tvb, offset, 4, FALSE);
-	  offset+=4;
-	  proto_tree_add_item(gen_tree, hf_generic_client_ver_req_length, tvb, offset, 4, FALSE);
-	  return offset+4;
-	case FAMILY_GENERIC_CLIENTVERREPL:
-	  proto_tree_add_item(gen_tree, hf_generic_client_ver_req_hash, tvb, offset, 16, FALSE);
-	  return 16;
-	case FAMILY_GENERIC_WELLKNOWNURL:
-	  /* FIXME */
-	  return 0;
-	case FAMILY_GENERIC_EXT_STATUS_REP:
-	  {
-		  guint8 length;
-	  proto_tree_add_item(gen_tree, hf_generic_ext_status_type, tvb, offset, 2, FALSE); offset += 2;
-	  proto_tree_add_item(gen_tree, hf_generic_ext_status_flags, tvb, offset, 1, FALSE); offset += 1;
-	  proto_tree_add_item(gen_tree, hf_generic_ext_status_length, tvb, offset, 1, FALSE); length = tvb_get_guint8(tvb, offset); offset += 1;
-	  proto_tree_add_item(gen_tree, hf_generic_ext_status_data, tvb, offset, length, FALSE); offset += 1;
-	  return offset;
-	  }
-	default: return 0;
-    }
-  return 0;
+	}
+	return offset;
 }
 
+static int dissect_aim_generic_clientver_req(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	int offset = 0;
+	proto_tree_add_item(gen_tree, hf_generic_client_ver_req_offset, tvb, offset, 4, FALSE);
+	offset+=4;
+	proto_tree_add_item(gen_tree, hf_generic_client_ver_req_length, tvb, offset, 4, FALSE);
+	return offset+4;
+}
+
+static int dissect_aim_generic_clientver_repl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	proto_tree_add_item(gen_tree, hf_generic_client_ver_req_hash, tvb, 0, 16, FALSE);
+	return 16;
+}
+
+static int dissect_aim_generic_ext_status_repl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *gen_tree)
+{
+	guint8 length;
+	int offset = 0;
+	proto_tree_add_item(gen_tree, hf_generic_ext_status_type, tvb, offset, 2, FALSE); offset += 2;
+	proto_tree_add_item(gen_tree, hf_generic_ext_status_flags, tvb, offset, 1, FALSE); offset += 1;
+	proto_tree_add_item(gen_tree, hf_generic_ext_status_length, tvb, offset, 1, FALSE); length = tvb_get_guint8(tvb, offset); offset += 1;
+	proto_tree_add_item(gen_tree, hf_generic_ext_status_data, tvb, offset, length, FALSE); offset += 1;
+	return offset;
+}
+
+static const aim_subtype aim_fnac_family_generic[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Client Ready", dissect_aim_generic_clientready },
+	{ 0x0003, "Server Ready", dissect_aim_generic_serverready  },
+	{ 0x0004, "Service Request", dissect_aim_generic_service_req },
+	{ 0x0005, "Redirect", dissect_aim_generic_redirect },
+	{ 0x0006, "Rate Info Request", NULL},
+	{ 0x0007, "Rate Info", dissect_generic_rateinfo },
+	{ 0x0008, "Rate Info Ack", dissect_aim_generic_rateinfoack },
+	{ 0x000a, "Rate Change", dissect_aim_generic_ratechange },
+	{ 0x000b, "Server Pause", NULL },
+	{ 0x000c, "Client Pause Ack", dissect_aim_generic_clientpauseack },
+	{ 0x000d, "Server Resume", NULL },
+	{ 0x000e, "Self Info Request", NULL },
+	{ 0x000f, "Self Info Reply", dissect_aim_generic_selfinfo_repl },
+	{ 0x0010, "Evil", dissect_aim_generic_evil },
+	{ 0x0011, "Set Idle", dissect_aim_generic_setidle },
+	{ 0x0012, "Migration Request", dissect_aim_generic_migration_req },
+	{ 0x0013, "Message Of The Day", dissect_aim_generic_motd },
+	{ 0x0014, "Set Privilege Flags", dissect_aim_generic_setprivflags },
+	{ 0x0015, "Well Known URL", NULL }, /* FIXME */
+	{ 0x0016, "noop", NULL },
+	{ 0x0017, "Capabilities",  dissect_aim_generic_capabilities },
+	{ 0x0018, "Capabilities Ack", dissect_aim_generic_capack },
+	{ 0x001e, "Set Extended Status Request", dissect_aim_generic_ext_status_req },
+	{ 0x001f, "Client Verification Request",  dissect_aim_generic_clientver_req },
+	{ 0x0020, "Client Verification Reply", dissect_aim_generic_clientver_repl },
+	{ 0x0021, "Set Extended Status Reply", dissect_aim_generic_ext_status_repl },
+	{ 0, NULL, NULL }
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_generic(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-	{ &hf_generic_servicereq_service, 
-	  { "Requested Service", "generic.servicereq.service", FT_UINT16,
-		  BASE_HEX, NULL, 0x0, "", HFILL },
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_generic_servicereq_service, 
+			{ "Requested Service", "generic.servicereq.service", FT_UINT16,
+				BASE_HEX, NULL, 0x0, "", HFILL },
 	},
 	{ &hf_generic_motd_motdtype, 
 	  { "MOTD Type", "generic.motd.motdtype", FT_UINT16,
@@ -603,8 +608,5 @@
 void
 proto_reg_handoff_aim_generic(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_generic, proto_aim_generic);
-  dissector_add("aim.family", FAMILY_GENERIC, aim_handle);
-  aim_init_family(FAMILY_GENERIC, "Generic", aim_fnac_family_generic);
+  aim_init_family(proto_aim_generic, ett_generic, FAMILY_GENERIC, aim_fnac_family_generic);
 }
Index: epan/dissectors/packet-aim.c
===================================================================
--- epan/dissectors/packet-aim.c	(revision 12042)
+++ epan/dissectors/packet-aim.c	(working copy)
@@ -246,6 +246,7 @@
 #define AIM_ONLINEBUDDY_UNKNOWN        0x000e
 #define AIM_ONLINEBUDDY_SESSIONLEN     0x000f
 #define AIM_ONLINEBUDDY_ICQSESSIONLEN  0x0010
+#define AIM_ONLINEBUDDY_AVAILMSG	   0x001d
 
 const aim_tlv onlinebuddy_tlvs[] = {
   { AIM_ONLINEBUDDY_USERCLASS, "User class", dissect_aim_tlv_value_userclass },
@@ -254,21 +255,16 @@
   { AIM_ONLINEBUDDY_STATUS, "Online status", dissect_aim_tlv_value_userstatus },
   { AIM_ONLINEBUDDY_IPADDR, "User IP Address", dissect_aim_tlv_value_ipv4 },
   { AIM_ONLINEBUDDY_DCINFO, "DC Info", dissect_aim_tlv_value_dcinfo},
-  { AIM_ONLINEBUDDY_CAPINFO, "Capability Info", dissect_aim_tlv_value_bytes },
+  { AIM_ONLINEBUDDY_CAPINFO, "Capability Info", dissect_aim_tlv_value_client_capabilities },
   { AIM_ONLINEBUDDY_MEMBERSINCE, "Member since", dissect_aim_tlv_value_time },
   { AIM_ONLINEBUDDY_UNKNOWN, "Unknown", dissect_aim_tlv_value_uint16 },
   { AIM_ONLINEBUDDY_TIMEUPDATE, "Time update", dissect_aim_tlv_value_bytes },
   { AIM_ONLINEBUDDY_SESSIONLEN, "Session Length (sec)", dissect_aim_tlv_value_uint32 },
   { AIM_ONLINEBUDDY_ICQSESSIONLEN, "ICQ Session Length (sec)", dissect_aim_tlv_value_uint32 },
+  { AIM_ONLINEBUDDY_AVAILMSG, "Available Message", dissect_aim_tlv_value_bytes },
   { 0, "Unknown", NULL }
 };
 
-struct aim_family {
-	guint16 family;
-	const char *name;
-	const value_string *subtypes;
-};
-
 static GList *families = NULL;
 
 #define AIM_MOTD_TLV_MOTD					   0x000B
@@ -473,13 +469,17 @@
   }
 
 }
-
-const char *aim_get_subtypename( guint16 famnum, guint16 subtype )
+const aim_subtype *aim_get_subtype( guint16 famnum, guint16 subtype )
 {
 	GList *gl = families;
 	while(gl) {
-		struct aim_family *fam = gl->data;
-		if(fam->family == famnum) return match_strval(subtype, fam->subtypes);
+		aim_family *fam = gl->data;
+		if(fam->family == famnum) {
+			int i;
+			for(i = 0; fam->subtypes[i].name; i++) {
+				if(fam->subtypes[i].id == subtype) return &(fam->subtypes[i]);
+			}
+		}
 		gl = gl->next;
 	}
 
@@ -487,12 +487,12 @@
 
 }
 
-const char *aim_get_familyname( guint16 famnum ) 
+const aim_family *aim_get_family( guint16 famnum ) 
 {
 	GList *gl = families;
 	while(gl) {
-		struct aim_family *fam = gl->data;
-		if(fam->family == famnum) return fam->name;
+		aim_family *fam = gl->data;
+		if(fam->family == famnum) return fam;
 		gl = gl->next;
 	}
 
@@ -589,13 +589,17 @@
   }
 }
 
-void aim_init_family(guint16 family, const char *name, const value_string *subtypes) 
+void aim_init_family(int proto, int ett, guint16 family, const aim_subtype *subtypes) 
 {
-	struct aim_family *fam = g_new(struct aim_family, 1);
-	fam->name = g_strdup(name);
+	aim_family *fam = g_new(aim_family, 1);
+	fam->proto = find_protocol_by_id(proto);
+	fam->name = proto_get_protocol_short_name(fam->proto);
 	fam->family = family;
 	fam->subtypes = subtypes;
 	families = g_list_append(families, fam);
+
+	fam->proto_id = proto;
+	fam->ett = ett;
 }
 
 static void dissect_aim_newconn(tvbuff_t *tvb, packet_info *pinfo, 
@@ -618,16 +622,16 @@
 
 
 int dissect_aim_snac_error(tvbuff_t *tvb, packet_info *pinfo, 
-			     int offset, proto_tree *aim_tree)
+			     proto_tree *aim_tree)
 {
   char *name;
-  if ((name = match_strval(tvb_get_ntohs(tvb, offset), aim_snac_errors)) != NULL) {
+  if ((name = match_strval(tvb_get_ntohs(tvb, 0), aim_snac_errors)) != NULL) {
      if (check_col(pinfo->cinfo, COL_INFO))
 		col_add_fstr(pinfo->cinfo, COL_INFO, name);
   }
 
   proto_tree_add_item (aim_tree, hf_aim_snac_error,
-			   tvb, offset, 2, FALSE);
+			   tvb, 0, 2, FALSE);
   return tvb_length_remaining(tvb, 2);
 }
 
@@ -653,45 +657,44 @@
 static void dissect_aim_snac(tvbuff_t *tvb, packet_info *pinfo, 
 			     int offset, proto_tree *aim_tree, proto_tree *root_tree)
 {
-  guint16 family;
-  guint16 subtype;
+  guint16 family_id;
+  guint16 subtype_id;
   guint16 flags;
   guint32 id;
   proto_item *ti1;
   struct aiminfo aiminfo;
-  const char *fam_name, *subtype_name;
   proto_tree *aim_tree_fnac = NULL;
   tvbuff_t *subtvb;
   int orig_offset;
+  const aim_subtype *subtype;
+  proto_tree *family_tree = NULL;
+  const aim_family *family;
 
   orig_offset = offset;
-  family = tvb_get_ntohs(tvb, offset);
-  fam_name = aim_get_familyname(family);
+  family_id = tvb_get_ntohs(tvb, offset);
+  family = aim_get_family(family_id);
   offset += 2;
-  subtype = tvb_get_ntohs(tvb, offset);
-  subtype_name = aim_get_subtypename(family, subtype);
+  subtype_id = tvb_get_ntohs(tvb, offset);
+  subtype = aim_get_subtype(family_id, subtype_id);
   offset += 2;
   flags = tvb_get_ntohs(tvb, offset);
   offset += 2;
   id = tvb_get_ntohl(tvb, offset);
   offset += 4;
   
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    col_add_fstr(pinfo->cinfo, COL_INFO, "SNAC data");
-  }
-  
+ 
   if( aim_tree )
     {
       offset = orig_offset;
-      ti1 = proto_tree_add_text(aim_tree, tvb, 6, 10, "FNAC");
+      ti1 = proto_tree_add_text(aim_tree, tvb, 6, 10, "FNAC: Family: 0x%04x, Subtype: %04x", family_id, subtype_id);
       aim_tree_fnac = proto_item_add_subtree(ti1, ett_aim_fnac);
 
       proto_tree_add_text (aim_tree_fnac, 
-			   tvb, offset, 2, "Family: %s (0x%04x)", fam_name?fam_name:"Unknown", family);
+			   tvb, offset, 2, "Family: %s (0x%04x)", family?family->name:"Unknown", family_id);
       offset += 2;
 
       proto_tree_add_text (aim_tree_fnac, 
-			   tvb, offset, 2, "Subtype: %s (0x%04x)", subtype_name?subtype_name:"Unknown", subtype);
+			   tvb, offset, 2, "Subtype: %s (0x%04x)", (subtype && subtype->name)?subtype->name:"Unknown", subtype_id);
       offset += 2;
 
       ti1 = proto_tree_add_uint(aim_tree_fnac, hf_aim_fnac_flags, tvb, offset, 
@@ -717,22 +720,38 @@
 
   subtvb = tvb_new_subset(tvb, offset, -1, -1);
   aiminfo.tcpinfo = pinfo->private_data;
-  aiminfo.family = family;
-  aiminfo.subtype = subtype;
+  aiminfo.family = family_id;
+  aiminfo.subtype = subtype_id;
   pinfo->private_data = &aiminfo;
+
+  if (check_col(pinfo->cinfo, COL_PROTOCOL) && family) {
+	col_set_str(pinfo->cinfo, COL_PROTOCOL, family->name);
+  }
   
   if (check_col(pinfo->cinfo, COL_INFO)) {
-     if(fam_name) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", fam_name);
-	 else col_append_fstr(pinfo->cinfo, COL_INFO, ", Family: 0x%04x", family);
-	 if(subtype_name) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", subtype_name);
-	 else col_append_fstr(pinfo->cinfo, COL_INFO, ", Subtype: 0x%04x", subtype);
+	 if(subtype) {
+		 col_set_str(pinfo->cinfo, COL_INFO, family->name);
+		 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", subtype->name);
+	 } else {
+	    col_set_str(pinfo->cinfo, COL_INFO, "SNAC data");
+	  
+     	if(family) col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", family->name);
+	 	else col_append_fstr(pinfo->cinfo, COL_INFO, ", Family: 0x%04x", family_id);
+
+	 	col_append_fstr(pinfo->cinfo, COL_INFO, ", Subtype: 0x%04x", subtype_id);
+	 }
   }
 
-  if(tvb_length_remaining(tvb, offset) == 0 || !dissector_try_port(subdissector_table, family, subtvb, pinfo, root_tree)) {
-    /* Show the undissected payload */
-    if (tvb_length_remaining(tvb, offset) > 0)
-      proto_tree_add_item(aim_tree, hf_aim_data, tvb, offset, -1, FALSE);
+  if(aim_tree && family) 
+  {
+	proto_item *ti = proto_tree_add_item(root_tree, family->proto_id, subtvb, 0, -1, FALSE); 
+	family_tree = proto_item_add_subtree(ti, family->ett);
+	if(subtype) proto_item_append_text(ti, ", %s", subtype->name);
   }
+
+  if(tvb_length_remaining(tvb, offset) > 0 && subtype && subtype->dissector) {
+	  subtype->dissector(subtvb, pinfo, family_tree);	 
+  }
 }
 
 static void dissect_aim_flap_err(tvbuff_t *tvb, packet_info *pinfo, 
@@ -922,10 +941,25 @@
 	 {0xf2e7c7f4, 0xfead, 0x4dfb,
 		 {0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}}},
 
+	{ "Unknown 1", 
+	 {0x0946f004, 0x4c7f, 0x11d1, 
+		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+
+	{ "Unknown 2", 
+	 {0x0946f004, 0x4c7f, 0x11d1, 
+		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+
+	{ "Unknown 3",
+	 {0x09460103, 0x4c7f, 0x11d1,
+		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+
+	{ "Unknown 4",
+	 {0x0946f003, 0x4c7f, 0x11d1,
+		 {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+
 	{ "Unknown", {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)
 {
 	int offset = 0;
@@ -937,28 +971,28 @@
 	
   	while (tvb_length_remaining(tvb, offset) > 0) {
 		int i;
-		const aim_client_capabilities *caps;
-		guint32 Data1 = tvb_get_ntoh24(tvb, offset);
-		guint16 Data2 = tvb_get_ntohs(tvb, offset+4);
-		guint16 Data3 = tvb_get_ntohs(tvb, offset+6);
-		guint8 Data4[8];
-		tvb_memcpy(tvb, Data4, offset+8, 8);
+		const aim_client_capabilities *caps = NULL;
+		e_uuid_t clsid;
 
-		caps = &client_caps[0];
+		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; !strcmp(client_caps[i].description, "Unknown"); i++) {
-			caps = &client_caps[i];
+		for(i = 0; client_caps[i].description; i++) {
 
-			if(Data1 == caps->clsid.Data1 && Data2 == caps->clsid.Data2 && 
-			   Data3 == caps->clsid.Data3 && !memcmp(caps->clsid.Data4, Data4, 8))
+			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 {%06x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 
-			caps->description, Data1, Data2, 
-			Data3, Data4[0], Data4[1], Data4[2], Data4[3], Data4[4],
-			Data4[5], Data4[6], Data4[7]
+			"%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;
Index: epan/dissectors/packet-aim-popup.c
===================================================================
--- epan/dissectors/packet-aim-popup.c	(revision 12042)
+++ epan/dissectors/packet-aim-popup.c	(working copy)
@@ -42,18 +42,7 @@
 /* SNAC families */
 #define FAMILY_POPUP      0x0008
 
-/* Family Popup */
-#define FAMILY_POPUP_ERROR            0x0001
-#define FAMILY_POPUP_COMMAND          0x0002
-#define FAMILY_POPUP_DEFAULT          0xffff
 
-static const value_string aim_fnac_family_popup[] = {
-  { FAMILY_POPUP_ERROR, "Error" },
-  { FAMILY_POPUP_COMMAND, "Display Popup Message Server Command" },
-  { FAMILY_POPUP_DEFAULT, "Popup Default" },
-  { 0, NULL }
-};
-
 #define AIM_POPUP_TLV_MESSAGE_TEXT		0x001
 #define AIM_POPUP_TLV_URL_STRING		0x002
 #define AIM_POPUP_TLV_WINDOW_WIDTH		0x003
@@ -75,29 +64,18 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_popup    = -1;
 
-static int dissect_aim_snac_popup(tvbuff_t *tvb, packet_info *pinfo, 
-								  proto_tree *tree) 
+static int dissect_aim_popup(tvbuff_t *tvb, packet_info *pinfo, proto_tree *popup_tree)
 {
-    int offset = 0;
-    struct aiminfo *aiminfo = pinfo->private_data;
-    proto_item *ti = NULL;
-    proto_tree *popup_tree = NULL;
-                                                                                
-    if(tree) {
-        ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Popup Service");
-        popup_tree = proto_item_add_subtree(ti, ett_aim_popup);
-    }
-                                                             
-	switch(aiminfo->subtype) {
-	case FAMILY_POPUP_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, 0, popup_tree);
-	case FAMILY_POPUP_COMMAND:
-	  return dissect_aim_tlv(tvb, pinfo, offset, popup_tree, popup_tlvs);
-	}
-
-	return 0;
+	return dissect_aim_tlv(tvb, pinfo, 0, popup_tree, popup_tlvs);
 }
 
+static const aim_subtype aim_fnac_family_popup[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Display Popup Message Server Command" , dissect_aim_popup },
+  { 0, NULL, NULL }
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_popup(void)
@@ -118,8 +96,5 @@
 void
 proto_reg_handoff_aim_popup(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_popup, proto_aim_popup);
-  dissector_add("aim.family", FAMILY_POPUP, aim_handle);
-  aim_init_family(FAMILY_POPUP, "Popup", aim_fnac_family_popup);
+  aim_init_family(proto_aim_popup, ett_aim_popup, FAMILY_POPUP, aim_fnac_family_popup);
 }
Index: epan/dissectors/packet-aim.h
===================================================================
--- epan/dissectors/packet-aim.h	(revision 12042)
+++ epan/dissectors/packet-aim.h	(working copy)
@@ -39,21 +39,36 @@
   struct tcpinfo *tcpinfo;
 };
 
-void aim_init_family(guint16 family, const char *name, const value_string *subtypes);
+typedef struct _aim_subtype {
+	guint16 id;
+	char *name;
+	int (*dissector) (tvbuff_t *, packet_info *, proto_tree *);
+} aim_subtype;
 
+typedef struct _aim_family {
+	int ett;
+	int proto_id;
+	protocol_t *proto;
+	guint16 family;
+	char *name;
+	const aim_subtype *subtypes;
+} aim_family;
+
+void aim_init_family(int proto, int ett, guint16 family, const aim_subtype *subtypes);
+
 int dissect_aim_buddyname(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
 void aim_get_message( guchar *msg, tvbuff_t *tvb, int msg_offset, int msg_length);
 int aim_get_buddyname( char *name, tvbuff_t *tvb, int len_offset, int name_offset);
 int dissect_aim_userinfo(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
 
 int dissect_aim_snac_error(tvbuff_t *tvb, packet_info *pinfo,
-                 int offset, proto_tree *aim_tree);
+                 proto_tree *aim_tree);
 
 int dissect_aim_tlv(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, const aim_tlv *);
 int dissect_aim_tlv_list(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, proto_tree *tree, const aim_tlv *);
 
-const char *aim_get_familyname( guint16 family );
-const char *aim_get_subtypename( guint16 family, guint16 subtype);
+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 *);
Index: epan/dissectors/packet-aim-signon.c
===================================================================
--- epan/dissectors/packet-aim-signon.c	(revision 12042)
+++ epan/dissectors/packet-aim-signon.c	(working copy)
@@ -42,36 +42,7 @@
 
 #define FAMILY_SIGNON     0x0017
 
-/* Family Signon */
-#define FAMILY_SIGNON_ERROR          0x0001
-#define FAMILY_SIGNON_LOGON          0x0002
-#define FAMILY_SIGNON_LOGON_REPLY    0x0003
-#define FAMILY_SIGNON_UIN_REQ        0x0004
-#define FAMILY_SIGNON_UIN_REPL       0x0005
-#define FAMILY_SIGNON_SIGNON         0x0006
-#define FAMILY_SIGNON_SIGNON_REPLY   0x0007
-#define FAMILY_SIGNON_S_SECUREID_REQ 0x000a
-#define FAMILY_SIGNON_C_SECUREID_REP 0x000b
 
-static const value_string aim_fnac_family_signon[] = {
-  { FAMILY_SIGNON_LOGON, "Logon" },
-  { FAMILY_SIGNON_LOGON_REPLY, "Logon Reply" },
-  { FAMILY_SIGNON_UIN_REQ, "Request UIN" },
-  { FAMILY_SIGNON_UIN_REPL, "New UIN response" },
-  { FAMILY_SIGNON_SIGNON, "Sign-on" },
-  { FAMILY_SIGNON_SIGNON_REPLY, "Sign-on Reply" },
-  { FAMILY_SIGNON_S_SECUREID_REQ, "Server SecureID Request" },
-  { FAMILY_SIGNON_C_SECUREID_REP, "Client SecureID Reply" },
-  { 0, NULL }
-};
-
-static int dissect_aim_snac_signon(tvbuff_t *tvb, packet_info *pinfo, 
-				    proto_tree *tree);
-static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
-static int dissect_aim_snac_signon_logon_reply(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
-static int dissect_aim_snac_signon_signon(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
-static int dissect_aim_snac_signon_signon_reply(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_signon = -1;
 static int hf_aim_infotype = -1;
@@ -82,59 +53,21 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_signon   = -1;
 
-static int dissect_aim_snac_signon(tvbuff_t *tvb, packet_info *pinfo, 
-				    proto_tree *tree)
+static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo, 
+					  proto_tree *tree)
 {
-	struct aiminfo *aiminfo = pinfo->private_data;
 	int offset = 0;
-
-	proto_item *ti = NULL;
-	proto_tree *signon_tree = NULL;
-	if(tree) {
-		ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Signon");
-		signon_tree = proto_item_add_subtree(ti, ett_aim_signon);
-	}                                                                                   
-	
-  switch(aiminfo->subtype)
-    {
-	case FAMILY_SIGNON_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, signon_tree);
-    case FAMILY_SIGNON_LOGON:
-      return dissect_aim_snac_signon_logon(tvb, pinfo, offset, signon_tree);
-    case FAMILY_SIGNON_LOGON_REPLY:
-      return dissect_aim_snac_signon_logon_reply(tvb, pinfo, offset, signon_tree);
-    case FAMILY_SIGNON_SIGNON:
-      return dissect_aim_snac_signon_signon(tvb, pinfo, offset, signon_tree);
-    case FAMILY_SIGNON_SIGNON_REPLY:
-      return dissect_aim_snac_signon_signon_reply(tvb, pinfo, offset, signon_tree);
-	case FAMILY_SIGNON_S_SECUREID_REQ:
-	  /* No data */
-	  return 0;
-	case FAMILY_SIGNON_UIN_REQ:
-	case FAMILY_SIGNON_UIN_REPL:
-	case FAMILY_SIGNON_C_SECUREID_REP:
-	/*FIXME*/	
-	default:
-	  return 0;
-    }
+	while (tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
+	}
+	return offset;
 }
 
-static int dissect_aim_snac_signon_logon(tvbuff_t *tvb, packet_info *pinfo, 
-					  int offset, proto_tree *tree)
-{
-  while (tvb_length_remaining(tvb, offset) > 0) {
-    offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
-  }
-  return offset;
-}
-
 static int dissect_aim_snac_signon_logon_reply(tvbuff_t *tvb, 
 						packet_info *pinfo, 
-						int offset, proto_tree *tree)
+						proto_tree *tree)
 {
-    if (check_col(pinfo->cinfo, COL_INFO)) 
-      col_append_fstr(pinfo->cinfo, COL_INFO, ", Login information reply");
-
+	int offset = 0;
     while (tvb_length_remaining(tvb, offset) > 0) {
       offset = dissect_aim_tlv(tvb, pinfo, offset, tree, client_tlvs);
     }
@@ -142,93 +75,99 @@
 }
 
 static int dissect_aim_snac_signon_signon(tvbuff_t *tvb, packet_info *pinfo, 
-					   int offset, proto_tree *tree)
+					   proto_tree *tree)
 {
-  guint8 buddyname_length = 0;
-  char buddyname[MAX_BUDDYNAME_LENGTH + 1];
+	guint8 buddyname_length = 0;
+	int offset = 0;
+	char buddyname[MAX_BUDDYNAME_LENGTH + 1];
 
-  /* Info Type */
-  proto_tree_add_item(tree, hf_aim_infotype, tvb, offset, 2, FALSE);
-  offset += 2;
+	/* Info Type */
+	proto_tree_add_item(tree, hf_aim_infotype, tvb, offset, 2, FALSE);
+	offset += 2;
 
-  /* Unknown */
-  offset += 1;
+	/* Unknown */
+	offset += 1;
 
-  /* Buddy Name */
-  buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
-  
-  if (check_col(pinfo->cinfo, COL_INFO)) {
-    col_append_fstr(pinfo->cinfo, COL_INFO, " Username: %s",
-                    format_text(buddyname, buddyname_length));
-  }
-  
-  if(tree) {
-    proto_tree_add_text(tree, tvb, offset + 1, buddyname_length, 
-			"Screen Name: %s",
-			format_text(buddyname, buddyname_length));
-  }
-  
-  offset += buddyname_length + 1;
-  return offset;
+	/* Buddy Name */
+	buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
+
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+		col_append_fstr(pinfo->cinfo, COL_INFO, " Username: %s",
+						format_text(buddyname, buddyname_length));
+	}
+
+	if(tree) {
+		offset+=dissect_aim_buddyname(tvb, pinfo, offset, tree);
+	}
+
+	return offset;
 }
 
 static int dissect_aim_snac_signon_signon_reply(tvbuff_t *tvb, 
-						 packet_info *pinfo, 
-						 int offset, proto_tree *tree)
+												packet_info *pinfo _U_, 
+												proto_tree *tree)
 {
-  guint16 challenge_length = 0;
+	int offset = 0;
+	guint16 challenge_length = 0;
 
-  if (check_col(pinfo->cinfo, COL_INFO)) 
-    col_append_fstr(pinfo->cinfo, COL_INFO, ", Sign-on reply");
+	/* Logon Challenge Length */
+	challenge_length = tvb_get_ntohs(tvb, offset);
+	proto_tree_add_item(tree, hf_aim_signon_challenge_len, tvb, offset, 2, FALSE);
+	offset += 2;
 
-  /* Logon Challenge Length */
-  challenge_length = tvb_get_ntohs(tvb, offset);
-  proto_tree_add_item(tree, hf_aim_signon_challenge_len, tvb, offset, 2, FALSE);
-  offset += 2;
-
-  /* Challenge */
-  proto_tree_add_item(tree, hf_aim_signon_challenge, tvb, offset, challenge_length, FALSE);
-  offset += challenge_length;
-  return offset;
+	/* Challenge */
+	proto_tree_add_item(tree, hf_aim_signon_challenge, tvb, offset, challenge_length, FALSE);
+	offset += challenge_length;
+	return offset;
 }
 
+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 },
+	{ 0x0006, "Sign-on", dissect_aim_snac_signon_signon },
+	{ 0x0007, "Sign-on Reply", dissect_aim_snac_signon_signon_reply },
+	{ 0x000a, "Server SecureID Request", NULL },
+	{ 0x000b, "Client SecureID Reply", NULL },
+	{ 0, NULL, NULL }
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_signon(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-    { &hf_aim_infotype,
-      { "Infotype", "aim.infotype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_signon_challenge_len,
-      { "Signon challenge length", "aim.signon.challengelen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_signon_challenge,
-      { "Signon challenge", "aim.signon.challenge", FT_STRING, BASE_HEX, NULL, 0x0, "", HFILL }
-    },
-  };
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_aim_infotype,
+			{ "Infotype", "aim.infotype", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_signon_challenge_len,
+			{ "Signon challenge length", "aim.signon.challengelen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_signon_challenge,
+			{ "Signon challenge", "aim.signon.challenge", FT_STRING, BASE_HEX, NULL, 0x0, "", HFILL }
+		},
+	};
 
-/* Setup protocol subtree array */
-  static gint *ett[] = {
-    &ett_aim_signon,
-  };
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_aim_signon,
+	};
 
-/* Register the protocol name and description */
-  proto_aim_signon = proto_register_protocol("AIM Signon", "AIM Signon", "aim_signon");
+	/* Register the protocol name and description */
+	proto_aim_signon = proto_register_protocol("AIM Signon", "AIM Signon", "aim_signon");
 
-/* Required function calls to register the header fields and subtrees used */
-  proto_register_field_array(proto_aim_signon, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_aim_signon, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
 }
 
 void
 proto_reg_handoff_aim_signon(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_signon, proto_aim_signon);
-  dissector_add("aim.family", FAMILY_SIGNON, aim_handle);
-  aim_init_family(FAMILY_SIGNON, "Signon", aim_fnac_family_signon);
+	aim_init_family(proto_aim_signon, ett_aim_signon, FAMILY_SIGNON, aim_fnac_family_signon);
 }
Index: epan/dissectors/packet-aim-chat.c
===================================================================
--- epan/dissectors/packet-aim-chat.c	(revision 12042)
+++ epan/dissectors/packet-aim-chat.c	(working copy)
@@ -45,30 +45,6 @@
 /* SNAC families */
 #define FAMILY_CHAT       0x000E
 
-/* Family Chat */
-#define FAMILY_CHAT_ERROR             0x0001
-#define FAMILY_CHAT_ROOMINFOUPDATE    0x0002
-#define FAMILY_CHAT_USERJOIN          0x0003
-#define FAMILY_CHAT_USERLEAVE         0x0004
-#define FAMILY_CHAT_OUTGOINGMSG       0x0005
-#define FAMILY_CHAT_INCOMINGMSG       0x0006
-#define FAMILY_CHAT_EVIL_REQ          0x0007
-#define FAMILY_CHAT_EVIL_REPLY        0x0008
-#define FAMILY_CHAT_DEFAULT           0xffff
-
-static const value_string aim_fnac_family_chat[] = {
-  { FAMILY_CHAT_ERROR, "Error" },
-  { FAMILY_CHAT_ROOMINFOUPDATE, "Room Info Update" },
-  { FAMILY_CHAT_USERJOIN, "User Join" },
-  { FAMILY_CHAT_USERLEAVE, "User Leave" },
-  { FAMILY_CHAT_OUTGOINGMSG, "Outgoing Message" },
-  { FAMILY_CHAT_INCOMINGMSG, "Incoming Message" },
-  { FAMILY_CHAT_EVIL_REQ, "Evil Request" },
-  { FAMILY_CHAT_EVIL_REPLY, "Evil Reply" },
-  { FAMILY_CHAT_DEFAULT, "Chat Default" },
-  { 0, NULL }
-};
-
 #define AIM_CHAT_TLV_BROWSABLE_TREE 		0x001
 #define AIM_CHAT_TLV_CLASS_EXCLUSIVE		0x002
 #define AIM_CHAT_TLV_MAX_CONCURRENT_ROOMS	0x003
@@ -98,67 +74,67 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_chat          = -1;
 
-static int dissect_aim_snac_chat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int dissect_aim_chat_userinfo_list(tvbuff_t *tvb, packet_info *pinfo, proto_tree *chat_tree)
 {
-  guint8 buddyname_length = 0;
-  int offset = 0;
-  struct aiminfo *aiminfo = pinfo->private_data;
-  char buddyname[MAX_BUDDYNAME_LENGTH + 1];
-  guchar msg[1000];
-  proto_item *ti;
-  proto_tree *chat_tree = NULL;
-                                                                                                                              
-  if(tree) {
-      ti = proto_tree_add_text(tree, tvb, 0, -1, "Chat Service");
-      chat_tree = proto_item_add_subtree(ti, ett_aim_chat);
-  }
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_userinfo(tvb, pinfo, offset, chat_tree);
+	}
+	return offset;
+}
 
-  switch(aiminfo->subtype)
-    {
-    case FAMILY_CHAT_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, chat_tree);
-    case FAMILY_CHAT_USERLEAVE:
-    case FAMILY_CHAT_USERJOIN:
-      while(tvb_length_remaining(tvb, offset) > 0) {
-        offset = dissect_aim_userinfo(tvb, pinfo, offset, chat_tree);
-      }
-      return offset;
-    case FAMILY_CHAT_EVIL_REQ:
-    case FAMILY_CHAT_EVIL_REPLY:
-    case FAMILY_CHAT_ROOMINFOUPDATE:
-      /* FIXME */
-      return 0;
-    case FAMILY_CHAT_OUTGOINGMSG:
-      /* channel message from client */
-      aim_get_message( msg, tvb, 40 + buddyname_length, tvb_length(tvb) 
-           - 40 - buddyname_length );
-      
-      if (check_col(pinfo->cinfo, COL_INFO)) 
-        col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);
-      return tvb_length(tvb);
-      
-    case FAMILY_CHAT_INCOMINGMSG:
-      /* channel message to client */
-      buddyname_length = aim_get_buddyname( buddyname, tvb, 30, 31 );
-      aim_get_message( msg, tvb, 36 + buddyname_length, tvb_length(tvb) 
-           - 36 - buddyname_length );
-      
-      if (check_col(pinfo->cinfo, COL_INFO)) {
-        col_append_fstr(pinfo->cinfo, COL_INFO, "from: %s", buddyname);
-        col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);
-      }
-      
-      if(chat_tree) {
-        proto_tree_add_text(chat_tree, tvb, 31, buddyname_length, 
-                            "Screen Name: %s",
-                            format_text(buddyname, buddyname_length));
-      }
-      return tvb_length(tvb);
-    default:
-      return 0;
-    }
+static int dissect_aim_chat_outgoing_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *chat_tree)
+{
+	char buddyname[MAX_BUDDYNAME_LENGTH+1];
+	guchar msg[1000];
+	int buddyname_length = aim_get_buddyname( buddyname, tvb, 30, 31 );
+
+	/* channel message from client */
+	aim_get_message( msg, tvb, 40 + buddyname_length, tvb_length(tvb) 
+					 - 40 - buddyname_length );
+
+	if (check_col(pinfo->cinfo, COL_INFO)) 
+		col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);
+	
+	return tvb_length(tvb);
 }
 
+
+static int dissect_aim_chat_incoming_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *chat_tree)
+{
+	char buddyname[MAX_BUDDYNAME_LENGTH+1];
+	guchar msg[1000];
+	/* channel message to client */
+	int buddyname_length = aim_get_buddyname( buddyname, tvb, 30, 31 );
+	
+	aim_get_message( msg, tvb, 36 + buddyname_length, tvb_length(tvb) 
+					 - 36 - buddyname_length );
+
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+		col_append_fstr(pinfo->cinfo, COL_INFO, "from: %s", buddyname);
+		col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", msg);
+	}
+
+	if(chat_tree) {
+		proto_tree_add_text(chat_tree, tvb, 31, buddyname_length, 
+							"Screen Name: %s",
+							format_text(buddyname, buddyname_length));
+	}
+	return tvb_length(tvb);
+}
+
+static const aim_subtype aim_fnac_family_chat[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Room Info Update", NULL },
+  { 0x0003, "User Join", dissect_aim_chat_userinfo_list },
+  { 0x0004, "User Leave", dissect_aim_chat_userinfo_list },
+  { 0x0005, "Outgoing Message", dissect_aim_chat_outgoing_msg },
+  { 0x0006, "Incoming Message", dissect_aim_chat_incoming_msg },
+  { 0x0007, "Evil Request", NULL },
+  { 0x0008, "Evil Reply", NULL },
+  { 0, NULL, NULL }
+};
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_chat(void)
@@ -186,8 +162,5 @@
 void
 proto_reg_handoff_aim_chat(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_chat, proto_aim_chat);
-  dissector_add("aim.family", FAMILY_CHAT, aim_handle);
-  aim_init_family(FAMILY_CHAT, "Chat", aim_fnac_family_chat);
+  aim_init_family(proto_aim_chat, ett_aim_chat, FAMILY_CHAT, aim_fnac_family_chat);
 }
Index: epan/dissectors/packet-aim-location.c
===================================================================
--- epan/dissectors/packet-aim-location.c	(revision 12042)
+++ epan/dissectors/packet-aim-location.c	(working copy)
@@ -43,32 +43,6 @@
 /* SNAC families */
 #define FAMILY_LOCATION   0x0002
 
-/* Family Location Services */
-#define FAMILY_LOCATION_ERROR         0x0001
-#define FAMILY_LOCATION_REQRIGHTS     0x0002
-#define FAMILY_LOCATION_RIGHTSINFO    0x0003
-#define FAMILY_LOCATION_SETUSERINFO   0x0004
-#define FAMILY_LOCATION_REQUSERINFO   0x0005
-#define FAMILY_LOCATION_USERINFO      0x0006
-#define FAMILY_LOCATION_WATCHERSUBREQ 0x0007
-#define FAMILY_LOCATION_WATCHERNOT    0x0008
-#define FAMILY_LOCATION_USER_INFO_QUERY 0x0015
-#define FAMILY_LOCATION_DEFAULT       0xffff
-
-static const value_string aim_fnac_family_location[] = {
-  { FAMILY_LOCATION_ERROR, "Error" },
-  { FAMILY_LOCATION_REQRIGHTS, "Request Rights" },
-  { FAMILY_LOCATION_RIGHTSINFO, "Rights Info" },
-  { FAMILY_LOCATION_SETUSERINFO, "Set User Info" },
-  { FAMILY_LOCATION_REQUSERINFO, "Request User Info" },
-  { FAMILY_LOCATION_USERINFO, "User Info" },
-  { FAMILY_LOCATION_WATCHERSUBREQ, "Watcher Subrequest" },
-  { FAMILY_LOCATION_WATCHERNOT, "Watcher Notification" },
-  { FAMILY_LOCATION_DEFAULT, "Location Default" },
-  { FAMILY_LOCATION_USER_INFO_QUERY, "User Info Query" },
-  { 0, NULL }
-};
-
 #define FAMILY_LOCATION_USERINFO_INFOENCODING  0x0001
 #define FAMILY_LOCATION_USERINFO_INFOMSG       0x0002
 #define FAMILY_LOCATION_USERINFO_AWAYENCODING  0x0003
@@ -114,9 +88,6 @@
   { 0, NULL }
 };
 
-static int dissect_aim_snac_location_request_user_information(tvbuff_t *tvb, int offset, proto_tree *tree);
-static int dissect_aim_snac_location_user_information(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *tree);
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_location = -1;
 static int hf_aim_snac_location_request_user_info_infotype = -1;
@@ -127,146 +98,142 @@
 /* Initialize the subtree pointers */
 static gint ett_aim_location    = -1;
 
-static int dissect_aim_location(tvbuff_t *tvb, packet_info *pinfo, 
-				      proto_tree *tree )
+static int dissect_aim_location_rightsinfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *loc_tree)
 {
-	struct aiminfo *aiminfo = pinfo->private_data;
 	int offset = 0;
-	 proto_item *ti = NULL;
-    proto_tree *loc_tree = NULL;
-
-    if(tree) {
-        ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Location Service");
-        loc_tree = proto_item_add_subtree(ti, ett_aim_location);
-    }
-
-  switch(aiminfo->subtype)
-    {
-	case FAMILY_LOCATION_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, loc_tree);
-    case FAMILY_LOCATION_REQUSERINFO:
-      return dissect_aim_snac_location_request_user_information(tvb, offset, loc_tree);
-    case FAMILY_LOCATION_USERINFO:
-      return dissect_aim_snac_location_user_information(tvb, pinfo, offset, loc_tree);
-	case FAMILY_LOCATION_REQRIGHTS:
-	  /* No data */
-	  return 0;
-	case FAMILY_LOCATION_RIGHTSINFO:
-	   while(tvb_length_remaining(tvb, offset) > 0) {
+	while(tvb_length_remaining(tvb, offset) > 0) {
 		offset = dissect_aim_tlv(tvb, pinfo, offset, loc_tree, location_rights_tlvs);
-	  }
-	  return 0;
-	case FAMILY_LOCATION_SETUSERINFO:
-	  while(tvb_length_remaining(tvb, offset) > 0) {
+	}
+	return offset;
+}
+
+static int dissect_aim_location_setuserinfo(tvbuff_t *tvb, packet_info *pinfo, proto_tree *loc_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
 		offset = dissect_aim_tlv(tvb, pinfo, offset, loc_tree, location_userinfo_tlvs);
-	  }
-	  return 0;
-	case FAMILY_LOCATION_WATCHERSUBREQ:
-	  /* FIXME */
-	  return 0;
-	case FAMILY_LOCATION_WATCHERNOT:
-	  while(tvb_length_remaining(tvb, offset) > 0) {
-		  offset = dissect_aim_buddyname(tvb, pinfo, offset, loc_tree);
-	  }
-	  return offset;
-	case FAMILY_LOCATION_USER_INFO_QUERY:
-	  offset = dissect_aim_buddyname(tvb, pinfo, offset+4, loc_tree);
-	  return offset;
-	default:
-	  return 0;
-    }
+	}
+	return offset;
 }
 
+static int dissect_aim_location_watcher_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *loc_tree)
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_buddyname(tvb, pinfo, offset, loc_tree);
+	}
+	return offset;
+}
+
+static int dissect_aim_location_user_info_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *loc_tree)
+{
+	return dissect_aim_buddyname(tvb, pinfo, 4, loc_tree);
+}
+
 static int dissect_aim_snac_location_request_user_information(tvbuff_t *tvb, 
-							  int offset,
-							  proto_tree *tree)
+															  packet_info *pinfo _U_,
+															  proto_tree *tree)
 {
-  guint8 buddyname_length = 0;
+	int offset = 0;
+	guint8 buddyname_length = 0;
 
-  /* Info Type */
-  proto_tree_add_item(tree, hf_aim_snac_location_request_user_info_infotype, 
-		      tvb, offset, 2, FALSE);
-  offset += 2;
+	/* Info Type */
+	proto_tree_add_item(tree, hf_aim_snac_location_request_user_info_infotype, 
+						tvb, offset, 2, FALSE);
+	offset += 2;
 
-  /* Buddy Name length */
-  buddyname_length = tvb_get_guint8(tvb, offset);
-  proto_tree_add_item(tree, hf_aim_buddyname_len, tvb, offset, 1, FALSE);
-  offset += 1;
-  
-  /* Buddy name */
-  proto_tree_add_item(tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
-  offset += buddyname_length;
+	/* Buddy Name length */
+	buddyname_length = tvb_get_guint8(tvb, offset);
+	proto_tree_add_item(tree, hf_aim_buddyname_len, tvb, offset, 1, FALSE);
+	offset += 1;
 
-  return offset;
+	/* Buddy name */
+	proto_tree_add_item(tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
+	offset += buddyname_length;
+
+	return offset;
 }
 
 static int dissect_aim_snac_location_user_information(tvbuff_t *tvb, 
-						       packet_info *pinfo _U_, 
-						  int offset, proto_tree *tree)
+													  packet_info *pinfo _U_, 
+													  proto_tree *tree)
 {
-  guint8 buddyname_length = 0;
+	int offset = 0;
+	guint8 buddyname_length = 0;
 
-  /* Buddy Name length */
-  buddyname_length = tvb_get_guint8(tvb, offset);
-  proto_tree_add_item(tree, hf_aim_buddyname_len, tvb, offset, 1, FALSE);
-  offset += 1;
-  
-  /* Buddy name */
-  proto_tree_add_item(tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
-  offset += buddyname_length;
+	/* Buddy Name length */
+	buddyname_length = tvb_get_guint8(tvb, offset);
+	proto_tree_add_item(tree, hf_aim_buddyname_len, tvb, offset, 1, FALSE);
+	offset += 1;
 
-  /* Warning level */
-  proto_tree_add_item(tree, hf_aim_userinfo_warninglevel, tvb, offset, 2, FALSE);
-  offset += 2;
+	/* Buddy name */
+	proto_tree_add_item(tree, hf_aim_buddyname, tvb, offset, buddyname_length, FALSE);
+	offset += buddyname_length;
 
-  offset = dissect_aim_tlv_list(tvb, pinfo, offset, tree, onlinebuddy_tlvs);
+	/* Warning level */
+	proto_tree_add_item(tree, hf_aim_userinfo_warninglevel, tvb, offset, 2, FALSE);
+	offset += 2;
 
-  while(tvb_length_remaining(tvb, offset) > 0) {
-	  offset = dissect_aim_tlv(tvb, pinfo, offset, tree, msg_tlv);
-  }
+	offset = dissect_aim_tlv_list(tvb, pinfo, offset, tree, onlinebuddy_tlvs);
 
-  return offset;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv(tvb, pinfo, offset, tree, msg_tlv);
+	}
+
+	return offset;
 }
 
+static const aim_subtype aim_fnac_family_location[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Request Rights", NULL },
+	{ 0x0003, "Rights Info", dissect_aim_location_rightsinfo },
+	{ 0x0004, "Set User Info", dissect_aim_location_setuserinfo },
+	{ 0x0005, "Request User Info", dissect_aim_snac_location_request_user_information },
+	{ 0x0006, "User Info", dissect_aim_snac_location_user_information },
+	{ 0x0007, "Watcher Subrequest", NULL },
+	{ 0x0008, "Watcher Notification", dissect_aim_location_watcher_notification },
+	{ 0x0015, "User Info Query", dissect_aim_location_user_info_query },
+	{ 0, NULL, NULL }
+};
+
+
+
 void
 proto_register_aim_location(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-    { &hf_aim_buddyname_len,
-      { "Buddyname len", "aim.buddynamelen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_buddyname,
-      { "Buddy Name", "aim.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_userinfo_warninglevel,
-      { "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_snac_location_request_user_info_infotype,
-      { "Infotype", "aim.snac.location.request_user_info.infotype", FT_UINT16, BASE_HEX, VALS(aim_snac_location_request_user_info_infotypes), 0x0,
-	"", HFILL }
-    },
-  };
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_aim_buddyname_len,
+			{ "Buddyname len", "aim.buddynamelen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_buddyname,
+			{ "Buddy Name", "aim.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
+		},
+		{ &hf_aim_userinfo_warninglevel,
+			{ "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+		{ &hf_aim_snac_location_request_user_info_infotype,
+			{ "Infotype", "aim.snac.location.request_user_info.infotype", FT_UINT16, BASE_HEX, VALS(aim_snac_location_request_user_info_infotypes), 0x0,
+				"", HFILL }
+		},
+	};
 
-/* Setup protocol subtree array */
-  static gint *ett[] = {
-    &ett_aim_location,
-  };
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_aim_location,
+	};
 
-/* Register the protocol name and description */
-  proto_aim_location = proto_register_protocol("AIM Location", "AIM Location", "aim_location");
+	/* Register the protocol name and description */
+	proto_aim_location = proto_register_protocol("AIM Location", "AIM Location", "aim_location");
 
-/* Required function calls to register the header fields and subtrees used */
-  proto_register_field_array(proto_aim_location, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_aim_location, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
 }
 
 void
 proto_reg_handoff_aim_location(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_location, proto_aim_location);
-  dissector_add("aim.family", FAMILY_LOCATION, aim_handle);
-  aim_init_family(FAMILY_LOCATION, "Location", aim_fnac_family_location);
+	aim_init_family(proto_aim_location, ett_aim_location, FAMILY_LOCATION, aim_fnac_family_location);
 }
Index: epan/dissectors/packet-aim-sst.c
===================================================================
--- epan/dissectors/packet-aim-sst.c	(revision 12042)
+++ epan/dissectors/packet-aim-sst.c	(working copy)
@@ -41,46 +41,23 @@
 
 #define FAMILY_SST    0x0010
 
-/* Family Advertising */
-#define FAMILY_SST_ERROR          		0x0001
-#define FAMILY_SST_UPLOAD_ICON_REQ	  	0x0002
-#define FAMILY_SST_UPLOAD_ICON_REPL	  	0x0003
-#define FAMILY_SST_DOWNLOAD_ICON_REQ	0x0004
-#define FAMILY_SST_DOWNLOAD_ICON_REPL	0x0005
 
-static const value_string aim_fnac_family_sst[] = {
-  { FAMILY_SST_ERROR, "Error" },
-  { FAMILY_SST_UPLOAD_ICON_REQ, "Upload Buddy Icon Request" },
-  { FAMILY_SST_UPLOAD_ICON_REPL, "Upload Buddy Icon Reply" },
-  { FAMILY_SST_DOWNLOAD_ICON_REQ, "Download Buddy Icon Request" },
-  { FAMILY_SST_DOWNLOAD_ICON_REPL, "Download Buddy Icon Reply" },
-  { 0, NULL }
-};
-
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_sst = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_sst      = -1;
 
-static int dissect_aim_sst(tvbuff_t *tvb _U_, 
-				     packet_info *pinfo _U_, 
-				     proto_tree *tree _U_)
-{
-	struct aiminfo *aiminfo = pinfo->private_data;
-	int offset = 0;
+static const aim_subtype aim_fnac_family_sst[] = {
+  { 0x0001, "Error", dissect_aim_snac_error },
+  { 0x0002, "Upload Buddy Icon Request", NULL },
+  { 0x0003, "Upload Buddy Icon Reply", NULL },
+  { 0x0004, "Download Buddy Icon Request", NULL },
+  { 0x0005, "Download Buddy Icon Reply", NULL },
+  { 0, NULL, NULL }
+};
 
-	switch(aiminfo->subtype) {
-		case FAMILY_SST_ERROR:
-		return dissect_aim_snac_error(tvb, pinfo, offset, tree);
-		default:
-		return 0;
-	}
 
-	return 0;
-}
-
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_sst(void)
@@ -108,8 +85,5 @@
 void
 proto_reg_handoff_aim_sst(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_sst, proto_aim_sst);
-  dissector_add("aim.family", FAMILY_SST, aim_handle);
-  aim_init_family(FAMILY_SST, "Server Stored Themes", aim_fnac_family_sst);
+  aim_init_family(proto_aim_sst, ett_aim_sst, FAMILY_SST, aim_fnac_family_sst);
 }
Index: epan/dissectors/packet-aim-email.c
===================================================================
--- epan/dissectors/packet-aim-email.c	(revision 12042)
+++ epan/dissectors/packet-aim-email.c	(working copy)
@@ -41,40 +41,19 @@
 
 #define FAMILY_EMAIL    0x0018
 
-/* Family Advertising */
-#define FAMILY_EMAIL_STATUS_REQ			0x0006
-#define FAMILY_EMAIL_STATUS_REPL		0x0007
-#define FAMILY_EMAIL_ACTIVATE			0x0016
-
-static const value_string aim_fnac_family_email[] = {
-  { FAMILY_EMAIL_STATUS_REQ, "Email Status Request" },
-  { FAMILY_EMAIL_STATUS_REPL, "Email Status Reply" },
-  { FAMILY_EMAIL_ACTIVATE, "Activate Email" },
-  { 0, NULL }
+static const aim_subtype aim_fnac_family_email[] = {
+  { 0x0006, "Email Status Request", NULL },
+  { 0x0007, "Email Status Reply", NULL },
+  { 0x0016, "Activate Email", NULL },
+  { 0, NULL, NULL }
 };
 
-
 /* Initialize the protocol and registered fields */
 static int proto_aim_email = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_email      = -1;
 
-static int dissect_aim_email(tvbuff_t *tvb _U_, 
-				     packet_info *pinfo _U_, 
-				     proto_tree *tree _U_)
-{
-	struct aiminfo *aiminfo = pinfo->private_data;
-
-	switch(aiminfo->subtype) {
-	default:
-			/* FIXME */
-		return 0;
-	}
-
-	return 0;
-}
-
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_email(void)
@@ -102,8 +81,5 @@
 void
 proto_reg_handoff_aim_email(void)
 {
-  dissector_handle_t aim_handle;
-  aim_handle = new_create_dissector_handle(dissect_aim_email, proto_aim_email);
-  dissector_add("aim.family", FAMILY_EMAIL, aim_handle);
-  aim_init_family(FAMILY_EMAIL, "E-mail", aim_fnac_family_email);
+  aim_init_family(proto_aim_email, ett_aim_email, FAMILY_EMAIL, aim_fnac_family_email);
 }
Index: epan/dissectors/packet-aim-buddylist.c
===================================================================
--- epan/dissectors/packet-aim-buddylist.c	(revision 12042)
+++ epan/dissectors/packet-aim-buddylist.c	(working copy)
@@ -42,32 +42,7 @@
 
 #define FAMILY_BUDDYLIST  0x0003
 
-/* Family Buddy List */
-#define FAMILY_BUDDYLIST_ERROR        0x0001
-#define FAMILY_BUDDYLIST_REQRIGHTS    0x0002
-#define FAMILY_BUDDYLIST_RIGHTSINFO   0x0003
-#define FAMILY_BUDDYLIST_ADDBUDDY     0x0004
-#define FAMILY_BUDDYLIST_REMBUDDY     0x0005
-#define FAMILY_BUDDYLIST_WATCHERS_REQ 0x0006
-#define FAMILY_BUDDYLIST_WATCHERS_REP 0x0007
-#define FAMILY_BUDDYLIST_REJECT       0x000a
-#define FAMILY_BUDDYLIST_ONCOMING     0x000b
-#define FAMILY_BUDDYLIST_OFFGOING     0x000c
-#define FAMILY_BUDDYLIST_DEFAULT      0xffff
 
-static const value_string aim_fnac_family_buddylist[] = {
-  { FAMILY_BUDDYLIST_ERROR, "Error" },
-  { FAMILY_BUDDYLIST_REQRIGHTS, "Request Rights" },
-  { FAMILY_BUDDYLIST_RIGHTSINFO, "Rights Info" },
-  { FAMILY_BUDDYLIST_ADDBUDDY, "Add Buddy" },
-  { FAMILY_BUDDYLIST_REMBUDDY, "Remove Buddy" },
-  { FAMILY_BUDDYLIST_REJECT, "Reject Buddy" }, 
-  { FAMILY_BUDDYLIST_ONCOMING, "Oncoming Buddy" },
-  { FAMILY_BUDDYLIST_OFFGOING, "Offgoing Buddy" },
-  { FAMILY_BUDDYLIST_DEFAULT, "Buddy Default" },
-  { 0, NULL }
-};
-
 #define AIM_BUDDYLIST_TLV_MAX_CONTACT_ENTRIES 		0x0001
 #define AIM_BUDDYLIST_TLV_MAX_WATCHER_ENTRIES 		0x0002
 #define AIM_BUDDYLIST_TLV_MAX_ONLINE_NOTIFICATIONS 	0x0003
@@ -82,154 +57,122 @@
 
 /* Initialize the protocol and registered fields */
 static int proto_aim_buddylist = -1;
-static int hf_aim_buddyname_len = -1;
-static int hf_aim_buddyname = -1;
 static int hf_aim_userinfo_warninglevel = -1;
-static int hf_aim_userinfo_tlvcount = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_aim_buddylist = -1;
 
-static int dissect_aim_snac_buddylist(tvbuff_t *tvb, packet_info *pinfo, 
-				       proto_tree *tree)
+static int dissect_aim_buddylist_buddylist(tvbuff_t *tvb, packet_info *pinfo, proto_tree *buddy_tree)
 {
-  guint8 buddyname_length = 0;
-  char buddyname[MAX_BUDDYNAME_LENGTH + 1];
-  guint16 tlv_count = 0;
-  struct aiminfo *aiminfo = pinfo->private_data;
-  int offset = 0;
-  proto_item *ti;
-  proto_tree *buddy_tree = NULL;
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_buddyname( tvb, pinfo, offset, buddy_tree);
+	}
+	return offset;
+}
 
-  if(tree) {
-	  ti = proto_tree_add_text(tree, tvb, 0, -1, "Buddy List Service");
-	  buddy_tree = proto_item_add_subtree(ti, ett_aim_buddylist);   
-  }
+static int dissect_aim_buddylist_rights_repl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *buddy_tree) 
+{
+	int offset = 0;
+	while(tvb_length_remaining(tvb, offset) > 0) {
+		offset = dissect_aim_tlv( tvb, pinfo, offset, buddy_tree, buddylist_tlvs);
+	}
+	return offset;
+}
 
+static int dissect_aim_buddylist_reject(tvbuff_t *tvb, packet_info *pinfo, proto_tree *buddy_tree)
+{
+	return dissect_aim_buddyname(tvb, pinfo, 0, buddy_tree);
+}
 
-  switch(aiminfo->subtype)
-    {
-	case FAMILY_BUDDYLIST_REQRIGHTS:
-	case FAMILY_BUDDYLIST_WATCHERS_REQ:
-		/* No data */
-		return 0;
-	case FAMILY_BUDDYLIST_REMBUDDY:
-	case FAMILY_BUDDYLIST_ADDBUDDY:
-	case FAMILY_BUDDYLIST_WATCHERS_REP:
-		while(tvb_length_remaining(tvb, offset) > 0) {
-			offset = dissect_aim_buddyname( tvb, pinfo, offset, buddy_tree);
-		}
-		return offset;
-	case FAMILY_BUDDYLIST_ERROR:
-      return dissect_aim_snac_error(tvb, pinfo, offset, buddy_tree);
-	case FAMILY_BUDDYLIST_RIGHTSINFO:
-		while(tvb_length_remaining(tvb, offset) > 0) {
-			offset = dissect_aim_tlv( tvb, pinfo, offset, buddy_tree, buddylist_tlvs);
-		}
-		return offset;
-	case FAMILY_BUDDYLIST_REJECT:
-		return dissect_aim_buddyname(tvb, pinfo, offset, buddy_tree);
-    case FAMILY_BUDDYLIST_ONCOMING:
-      buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
+static int dissect_aim_buddylist_oncoming(tvbuff_t *tvb, packet_info *pinfo, proto_tree *buddy_tree)
+{
+	char buddyname[MAX_BUDDYNAME_LENGTH+1];
+	int offset = 0;
+	int buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
 
-      if (check_col(pinfo->cinfo, COL_INFO)) {
-	col_add_fstr(pinfo->cinfo, COL_INFO, "Oncoming Buddy");
-	col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
-	                format_text(buddyname, buddyname_length));
-      }
-      
-      if (buddy_tree) {
-	proto_tree_add_text(buddy_tree, tvb, offset + 1, buddyname_length, 
-			    "Screen Name: %s",
-			    format_text(buddyname, buddyname_length));
-      }
-      offset += buddyname_length + 1;
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+		col_add_fstr(pinfo->cinfo, COL_INFO, "Oncoming Buddy");
+		col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+						format_text(buddyname, buddyname_length));
+	}
 
-      /* Warning level */
-      proto_tree_add_item(buddy_tree, hf_aim_userinfo_warninglevel, tvb, offset, 
-			  2, FALSE);
-      offset += 2;
-      
-      /* TLV Count */
-      tlv_count = tvb_get_ntohs(tvb, offset);
-      proto_tree_add_item(buddy_tree, hf_aim_userinfo_tlvcount, tvb, offset, 
-			  2, FALSE);
-      offset += 2;
+	offset += dissect_aim_buddyname(tvb, pinfo, offset, buddy_tree);
 
-      while (tvb_length_remaining(tvb, offset) > 0) {
-	offset = dissect_aim_tlv(tvb, pinfo, offset, buddy_tree, onlinebuddy_tlvs);
-      }
+	/* Warning level */
+	proto_tree_add_item(buddy_tree, hf_aim_userinfo_warninglevel, tvb, offset, 
+						2, FALSE);
+	offset += 2;
 
-      return offset;
-      
-    case FAMILY_BUDDYLIST_OFFGOING:
-      buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
-      
-      if (check_col(pinfo->cinfo, COL_INFO)) {
-	col_add_fstr(pinfo->cinfo, COL_INFO, "Offgoing Buddy");
-	col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
-	                format_text(buddyname, buddyname_length));
-      }
-      
-      if (buddy_tree) {
-	proto_tree_add_text(buddy_tree, tvb, offset + 1, buddyname_length, 
-			    "Screen Name: %s",
-			    format_text(buddyname, buddyname_length));
-      }
-      offset += buddyname_length + 1;
+	offset = dissect_aim_tlv_list(tvb, pinfo, offset, buddy_tree, onlinebuddy_tlvs);
 
-      /* Warning level */
-      proto_tree_add_item(buddy_tree, hf_aim_userinfo_warninglevel, tvb, offset, 
-			  2, FALSE);
-      offset += 2;
+	return offset;
+}
 
-	  return dissect_aim_tlv_list(tvb, pinfo, offset, buddy_tree, onlinebuddy_tlvs);
-	default:
-	  return 0;
-    }
+static int dissect_aim_buddylist_offgoing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *buddy_tree) 
+{
+
+	char buddyname[MAX_BUDDYNAME_LENGTH+1];
+	int offset = 0;
+	int buddyname_length = aim_get_buddyname( buddyname, tvb, offset, offset + 1 );
+
+	if (check_col(pinfo->cinfo, COL_INFO)) {
+		col_add_fstr(pinfo->cinfo, COL_INFO, "Offgoing Buddy");
+		col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
+						format_text(buddyname, buddyname_length));
+	}
+
+	offset += dissect_aim_buddyname(tvb, pinfo, offset, buddy_tree);
+
+	/* Warning level */
+	proto_tree_add_item(buddy_tree, hf_aim_userinfo_warninglevel, tvb, offset, 
+						2, FALSE);
+	offset += 2;
+
+	return dissect_aim_tlv_list(tvb, pinfo, offset, buddy_tree, onlinebuddy_tlvs);
 }
 
+static const aim_subtype aim_fnac_family_buddylist[] = {
+	{ 0x0001, "Error", dissect_aim_snac_error },
+	{ 0x0002, "Rights Request", NULL },
+	{ 0x0003, "Rights Reply", dissect_aim_buddylist_rights_repl },
+	{ 0x0004, "Add Buddy", dissect_aim_buddylist_buddylist },
+	{ 0x0005, "Remove Buddy", dissect_aim_buddylist_buddylist },
+	{ 0x0006, "Watchers List Request", NULL },
+	{ 0x0007, "Watchers List Reply", dissect_aim_buddylist_buddylist },
+	{ 0x000a, "Reject Buddy", dissect_aim_buddylist_reject }, 
+	{ 0x000b, "Oncoming Buddy", dissect_aim_buddylist_oncoming },
+	{ 0x000c, "Offgoing Buddy", dissect_aim_buddylist_offgoing },
+	{ 0, NULL, NULL }
+};
 
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_buddylist(void)
 {
 
-/* Setup list of header fields */
-  static hf_register_info hf[] = {
-    { &hf_aim_buddyname_len,
-      { "Buddyname len", "aim.buddynamelen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_buddyname,
-      { "Buddy Name", "aim.buddyname", FT_STRING, BASE_NONE, NULL, 0x0, "", HFILL }
-    },
-    { &hf_aim_userinfo_warninglevel,
-      { "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-    { &hf_aim_userinfo_tlvcount,
-      { "TLV Count", "aim.userinfo.tlvcount", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
-    },
-  };
+	/* Setup list of header fields */
+	static hf_register_info hf[] = {
+		{ &hf_aim_userinfo_warninglevel,
+			{ "Warning Level", "aim.userinfo.warninglevel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
+		},
+	};
 
-/* Setup protocol subtree array */
-  static gint *ett[] = {
-    &ett_aim_buddylist,
-  };
+	/* Setup protocol subtree array */
+	static gint *ett[] = {
+		&ett_aim_buddylist,
+	};
 
-/* Register the protocol name and description */
-  proto_aim_buddylist = proto_register_protocol("AIM Buddylist Service", "AIM Buddylist", "aim_buddylist");
+	/* Register the protocol name and description */
+	proto_aim_buddylist = proto_register_protocol("AIM Buddylist Service", "AIM Buddylist", "aim_buddylist");
 
-/* Required function calls to register the header fields and subtrees used */
-  proto_register_field_array(proto_aim_buddylist, hf, array_length(hf));
-  proto_register_subtree_array(ett, array_length(ett));
+	/* Required function calls to register the header fields and subtrees used */
+	proto_register_field_array(proto_aim_buddylist, hf, array_length(hf));
+	proto_register_subtree_array(ett, array_length(ett));
 }
 
 void
 proto_reg_handoff_aim_buddylist(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_snac_buddylist, proto_aim_buddylist);
-  dissector_add("aim.family", FAMILY_BUDDYLIST, aim_handle);
-  aim_init_family(FAMILY_BUDDYLIST, "Buddylist", aim_fnac_family_buddylist);
+	aim_init_family(proto_aim_buddylist, ett_aim_buddylist, FAMILY_BUDDYLIST, aim_fnac_family_buddylist);
 }
Index: epan/dissectors/packet-aim-icq.c
===================================================================
--- epan/dissectors/packet-aim-icq.c	(revision 12042)
+++ epan/dissectors/packet-aim-icq.c	(working copy)
@@ -41,22 +41,7 @@
 
 #define FAMILY_ICQ        0x0015
 
-/* Family ICQ */
-#define FAMILY_ICQ_ERROR              0x0001
-#define FAMILY_ICQ_LOGINREQUEST       0x0002
-#define FAMILY_ICQ_LOGINRESPONSE      0x0003
-#define FAMILY_ICQ_AUTHREQUEST        0x0006
-#define FAMILY_ICQ_AUTHRESPONSE       0x0007
 
-static const value_string aim_fnac_family_icq[] = {
-  { FAMILY_ICQ_ERROR, "Error" },
-  { FAMILY_ICQ_LOGINREQUEST, "Login Request" },
-  { FAMILY_ICQ_LOGINRESPONSE, "Login Response" },
-  { FAMILY_ICQ_AUTHREQUEST, "Auth Request" },
-  { FAMILY_ICQ_AUTHRESPONSE, "Auth Response" },
-  { 0, NULL }
-};
-
 #define ICQ_CLI_OFFLINE_MESSAGE_REQ 	0x003c
 #define ICQ_CLI_DELETE_OFFLINE_MSGS		0x003e
 #define ICQ_SRV_END_OF_OFFLINE_MSGS		0x0042
@@ -72,8 +57,9 @@
   { 0, NULL }
 };
 
-int dissect_aim_tlv_value_icq(proto_item *ti, guint16, tvbuff_t *);
 
+static int dissect_aim_tlv_value_icq(proto_item *ti, guint16 subtype, tvbuff_t *tvb);
+
 #define TLV_ICQ_META_DATA 			  0x0001
 
 static const aim_tlv icq_tlv[] = {
@@ -88,13 +74,12 @@
 static gint ett_aim_icq      = -1;
 static gint ett_aim_icq_tlv  = -1;
 
-
 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_tlv_request_seq_num = -1;
 
-int dissect_aim_tlv_value_icq(proto_item *ti _U_, guint16 subtype _U_, tvbuff_t *tvb _U_)
+static int dissect_aim_tlv_value_icq(proto_item *ti _U_, guint16 subtype _U_, tvbuff_t *tvb _U_)
 {
 	int offset = 0;
 	proto_tree *t = proto_item_add_subtree(ti, ett_aim_icq_tlv);
@@ -115,25 +100,21 @@
 	return 0;
 }
 
-static int dissect_aim_icq(tvbuff_t *tvb, packet_info *pinfo, 
-				    proto_tree *tree)
+static int dissect_aim_icq_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-   struct aiminfo *aiminfo = pinfo->private_data;
-   int offset = 0;
-   switch(aiminfo->subtype) {
-   case FAMILY_ICQ_ERROR:
-	   return dissect_aim_snac_error(tvb, pinfo, offset, tree);
-   case FAMILY_ICQ_LOGINREQUEST:
-   case FAMILY_ICQ_LOGINRESPONSE:
-	   return dissect_aim_tlv(tvb, pinfo, offset, tree, icq_tlv);
-   case FAMILY_ICQ_AUTHREQUEST:
-   case FAMILY_ICQ_AUTHRESPONSE:
-	   /* FIXME */
-	default:
-	   return 0;
-   }
+	return dissect_aim_tlv(tvb, pinfo, 0, tree, icq_tlv);
 }
 
+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 },
+  { 0x0006, "Auth Request", NULL },
+  { 0x0007, "Auth Response", NULL },
+  { 0, NULL, NULL }
+};
+
+
 /* Register the protocol with Ethereal */
 void
 proto_register_aim_icq(void)
@@ -172,9 +153,5 @@
 void
 proto_reg_handoff_aim_icq(void)
 {
-  dissector_handle_t aim_handle;
-
-  aim_handle = new_create_dissector_handle(dissect_aim_icq, proto_aim_icq);
-  dissector_add("aim.family", FAMILY_ICQ, aim_handle);
-  aim_init_family(FAMILY_ICQ, "ICQ", aim_fnac_family_icq);
+  aim_init_family(proto_aim_icq, ett_aim_icq, FAMILY_ICQ, aim_fnac_family_icq);
 }

Attachment: signature.asc
Description: Digital signature