From Clinton Work: dissect Cisco PID 0x010b as STP (it's actually their
[obnox/wireshark/wip.git] / packet-aim-generic.c
1 /* packet-aim-generic.c
2  * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Family Generic
3  * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
4  *
5  * $Id: packet-aim-generic.c,v 1.1 2004/03/23 06:21:16 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <ctype.h>
34
35 #include <glib.h>
36
37 #include <epan/packet.h>
38 #include <epan/strutil.h>
39
40 #include "packet-aim.h"
41 #include "prefs.h"
42
43 #define STRIP_TAGS 1
44
45 /* SNAC families */
46 #define FAMILY_GENERIC    0x0001
47
48 /* Family Generic */
49 #define FAMILY_GENERIC_ERROR          0x0001
50 #define FAMILY_GENERIC_CLIENTREADY    0x0002
51 #define FAMILY_GENERIC_SERVERREADY    0x0003
52 #define FAMILY_GENERIC_SERVICEREQ     0x0004
53 #define FAMILY_GENERIC_REDIRECT       0x0005
54 #define FAMILY_GENERIC_RATEINFOREQ    0x0006
55 #define FAMILY_GENERIC_RATEINFO       0x0007
56 #define FAMILY_GENERIC_RATEINFOACK    0x0008
57 #define FAMILY_GENERIC_UNKNOWNx09     0x0009
58 #define FAMILY_GENERIC_RATECHANGE     0x000a
59 #define FAMILY_GENERIC_SERVERPAUSE    0x000b
60 #define FAMILY_GENERIC_CLIENTPAUSEACK 0x000c
61 #define FAMILY_GENERIC_SERVERRESUME   0x000d
62 #define FAMILY_GENERIC_REQSELFINFO    0x000e
63 #define FAMILY_GENERIC_SELFINFO       0x000f
64 #define FAMILY_GENERIC_EVIL           0x0010
65 #define FAMILY_GENERIC_SETIDLE        0x0011
66 #define FAMILY_GENERIC_MIGRATIONREQ   0x0012
67 #define FAMILY_GENERIC_MOTD           0x0013
68 #define FAMILY_GENERIC_SETPRIVFLAGS   0x0014
69 #define FAMILY_GENERIC_WELLKNOWNURL   0x0015
70 #define FAMILY_GENERIC_NOP            0x0016
71 #define FAMILY_GENERIC_CAPABILITIES   0x0017
72 #define FAMILY_GENERIC_CAPACK         0x0018
73 #define FAMILY_GENERIC_SETSTATUS      0x001e
74 #define FAMILY_GENERIC_CLIENTVERREQ   0x001f
75 #define FAMILY_GENERIC_CLIENTVERREPL  0x0020
76 #define FAMILY_GENERIC_DEFAULT        0xffff
77
78 static const value_string aim_fnac_family_generic[] = {
79   { FAMILY_GENERIC_ERROR, "Error" },
80   { FAMILY_GENERIC_CLIENTREADY , "Client Ready" },
81   { FAMILY_GENERIC_SERVERREADY, "Server Ready" },
82   { FAMILY_GENERIC_SERVICEREQ, "Service Request" },
83   { FAMILY_GENERIC_REDIRECT, "Redirect" },
84   { FAMILY_GENERIC_RATEINFOREQ, "Rate Info Request" },
85   { FAMILY_GENERIC_RATEINFO, "Rate Info" },
86   { FAMILY_GENERIC_RATEINFOACK, "Rate Info Ack" },
87   { FAMILY_GENERIC_UNKNOWNx09, "Unknown" },
88   { FAMILY_GENERIC_RATECHANGE, "Rate Change" },
89   { FAMILY_GENERIC_SERVERPAUSE, "Server Pause" },
90   { FAMILY_GENERIC_CLIENTPAUSEACK, "Client Pause Ack" },
91   { FAMILY_GENERIC_SERVERRESUME, "Server Resume" },
92   { FAMILY_GENERIC_REQSELFINFO, "Self Info Request" },
93   { FAMILY_GENERIC_SELFINFO, "Self Info" },
94   { FAMILY_GENERIC_EVIL, "Evil" },
95   { FAMILY_GENERIC_SETIDLE, "Set Idle" },
96   { FAMILY_GENERIC_MIGRATIONREQ, "Migration Request" },
97   { FAMILY_GENERIC_MOTD, "Message Of The Day" },
98   { FAMILY_GENERIC_SETPRIVFLAGS, "Set Privilege Flags" },
99   { FAMILY_GENERIC_WELLKNOWNURL, "Well Known URL" },
100   { FAMILY_GENERIC_NOP, "noop" },
101   { FAMILY_GENERIC_CAPABILITIES, "Capabilities (ICQ specific)" },
102   { FAMILY_GENERIC_CAPACK, "Capabilities Ack (ICQ specific)" },
103   { FAMILY_GENERIC_SETSTATUS, "Set Status (ICQ specific)" },
104   { FAMILY_GENERIC_CLIENTVERREQ, "Client Verification Requst" },
105   { FAMILY_GENERIC_CLIENTVERREPL, "Client Verification Reply" },
106   { FAMILY_GENERIC_DEFAULT, "Generic Default" },
107   { 0, NULL }
108 };
109
110 #define FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE       0x0001
111 #define FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE       0x0002
112 #define FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN      0x0003
113 #define FAMILY_GENERIC_MOTD_MOTDTYPE_NORMAL            0x0004
114 #define FAMILY_GENERIC_MOTD_MOTDTYPE_NEWS              0x0006
115
116 static const value_string aim_snac_generic_motd_motdtypes[] = {
117   { FAMILY_GENERIC_MOTD_MOTDTYPE_MDT_UPGRADE, "Mandatory Upgrade Needed Notice" },
118   { FAMILY_GENERIC_MOTD_MOTDTYPE_ADV_UPGRADE, "Advisable Upgrade Notice" },
119   { FAMILY_GENERIC_MOTD_MOTDTYPE_SYS_BULLETIN, "AIM/ICQ Service System Announcements" },
120   { FAMILY_GENERIC_MOTD_MOTDTYPE_NORMAL, "Standard Notice" },
121   { FAMILY_GENERIC_MOTD_MOTDTYPE_NEWS, "News from AOL service" },
122   { 0, NULL }
123 };
124
125 #define RATEINFO_STATE_LIMITED                  0x01
126 #define RATEINFO_STATE_ALERT                    0x02
127 #define RATEINFO_STATE_CLEAR                    0x03
128
129 static const value_string rateinfo_states[] = {
130         { RATEINFO_STATE_LIMITED, "Limited" },
131         { RATEINFO_STATE_ALERT, "Alert" },
132         { RATEINFO_STATE_CLEAR, "Clear" },
133         { 0, NULL }
134 };
135
136 #define RATECHANGE_MSG_LIMIT_PARAMS_CHANGED      0x0001
137 #define RATECHANGE_MSG_LIMIT_WARN                0x0002
138 #define RATECHANGE_MSG_LIMIT_HIT                 0x0003
139 #define RATECHANGE_MSG_LIMIT_CLEAR               0x0004
140
141 static const value_string ratechange_msgs[] = {
142         { RATECHANGE_MSG_LIMIT_PARAMS_CHANGED, "Rate limits parameters changed" },
143         { RATECHANGE_MSG_LIMIT_WARN, "Rate limits warning (current level < alert level)" },
144         { RATECHANGE_MSG_LIMIT_HIT, "Rate limit hit (current level < limit level)" },
145         { RATECHANGE_MSG_LIMIT_CLEAR, "Rate limit clear (current level now > clear level)" },
146         { 0, NULL },
147 };
148
149 static int dissect_aim_snac_generic(tvbuff_t *tvb, packet_info *pinfo, 
150                                      proto_tree *tree);
151
152 /* Initialize the protocol and registered fields */
153 static int proto_aim_generic = -1;
154 static int hf_generic_motd_motdtype = -1;
155 static int hf_generic_servicereq_service = -1;
156 static int hf_generic_rateinfo_numclasses = -1;
157 static int hf_generic_rateinfo_windowsize = -1;
158 static int hf_generic_rateinfo_clearlevel = -1;
159 static int hf_generic_rateinfo_alertlevel = -1;
160 static int hf_generic_rateinfo_limitlevel = -1;
161 static int hf_generic_rateinfo_disconnectlevel = -1;
162 static int hf_generic_rateinfo_currentlevel = -1;
163 static int hf_generic_rateinfo_maxlevel = -1;
164 static int hf_generic_rateinfo_lasttime = -1;
165 static int hf_generic_rateinfo_curstate = -1;
166 static int hf_generic_rateinfo_classid = -1;
167 static int hf_generic_rateinfo_numpairs = -1;
168 static int hf_generic_rateinfoack_group = -1;
169 static int hf_generic_ratechange_msg    = -1;
170 static int hf_generic_migration_numfams  = -1;
171 static int hf_generic_priv_flags = -1;
172 static int hf_generic_allow_idle_see = -1;
173 static int hf_generic_allow_member_see = -1;
174
175 /* Initialize the subtree pointers */
176 static gint ett_generic_clientready = -1;
177 static gint ett_generic_migratefamilies = -1;
178 static gint ett_generic_clientready_item = -1;
179 static gint ett_generic_serverready = -1;
180 static gint ett_generic = -1;
181 static gint ett_generic_priv_flags = -1;
182 static gint ett_generic_rateinfo_class = -1;
183 static gint ett_generic_rateinfo_classes = -1;
184 static gint ett_generic_rateinfo_groups = -1;
185 static gint ett_generic_rateinfo_group = -1;
186
187 static int dissect_rate_class(tvbuff_t *tvb, packet_info *pinfo _U_, int offset,
188                                         proto_tree *class_tree) {
189         proto_tree_add_uint(class_tree, hf_generic_rateinfo_classid, tvb, offset, 2, tvb_get_ntohs(tvb, offset));offset+=2;
190         proto_tree_add_uint(class_tree, hf_generic_rateinfo_windowsize, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
191         proto_tree_add_uint(class_tree, hf_generic_rateinfo_clearlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
192         proto_tree_add_uint(class_tree, hf_generic_rateinfo_alertlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
193         proto_tree_add_uint(class_tree, hf_generic_rateinfo_limitlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
194         proto_tree_add_uint(class_tree, hf_generic_rateinfo_disconnectlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
195         proto_tree_add_uint(class_tree, hf_generic_rateinfo_currentlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
196         proto_tree_add_uint(class_tree, hf_generic_rateinfo_maxlevel, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
197         proto_tree_add_uint(class_tree, hf_generic_rateinfo_lasttime, tvb, offset, 4, tvb_get_ntoh24(tvb, offset));offset+=4;
198         proto_tree_add_uint(class_tree, hf_generic_rateinfo_curstate, tvb, offset, 1, tvb_get_guint8(tvb, offset));offset+=1;
199         return offset;
200 }
201
202 static int dissect_generic_rateinfo(tvbuff_t *tvb, packet_info *pinfo _U_, 
203                                     proto_tree *tree) {
204         int offset = 0;
205         guint16 i;
206         proto_item *ti;
207         guint16 numclasses = tvb_get_ntohs(tvb, 0);     
208         proto_tree *classes_tree, *groups_tree, *group_tree;
209     proto_tree_add_uint(tree, hf_generic_rateinfo_numclasses, tvb, 0, 2, numclasses );
210         offset+=2;
211
212         ti = proto_tree_add_text(tree, tvb, offset, 33*numclasses, "Available Rate Classes");
213         classes_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_classes);
214
215         for(i = 0; i < numclasses; i++) {
216                 guint16 myid = tvb_get_ntohs(tvb, offset); 
217                 proto_item *ti = proto_tree_add_text(classes_tree, tvb, offset, 33,"Rate Class 0x%02x", myid);
218                 proto_tree *class_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_class);
219                 offset = dissect_rate_class(tvb, pinfo, offset, class_tree);
220         }
221
222         ti = proto_tree_add_text(tree, tvb, offset, -1, "Rate Groups");
223         groups_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_groups);
224
225         for(i = 0; i < numclasses; i++) {
226                 guint16 myid = tvb_get_ntohs(tvb, offset); 
227                 guint16 j;
228                 guint16 numpairs;
229
230                 proto_item *ti = proto_tree_add_text(groups_tree, tvb, offset, 33,"Rate Group 0x%02x", myid);
231                 group_tree = proto_item_add_subtree(ti, ett_generic_rateinfo_group);
232                 proto_tree_add_uint(group_tree, hf_generic_rateinfo_classid, tvb, offset, 2, myid);offset+=2;
233                 numpairs = tvb_get_ntohs(tvb, offset);
234                 proto_tree_add_uint(group_tree, hf_generic_rateinfo_numpairs, tvb, offset, 2, numpairs); offset+=2;
235                 for(j = 0; j < numpairs; j++) {
236                         const char *fam_name, *subtype_name;
237                         guint16 family; 
238                         guint16 subtype;
239                         family = tvb_get_ntohs(tvb, offset); offset+=2;
240                         subtype = tvb_get_ntohs(tvb, offset); offset+=2;
241
242                         fam_name = aim_get_familyname(family);
243                         subtype_name = aim_get_subtypename(family, subtype);
244
245                         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);
246                 }
247         }
248         
249         return offset;
250 }
251
252 static int dissect_aim_snac_generic(tvbuff_t *tvb, packet_info *pinfo, 
253                                     proto_tree *tree)
254 {
255   int offset = 0;
256   const char *name;
257   struct aiminfo *aiminfo = pinfo->private_data;
258   guint16 n, i;
259   proto_item *ti = NULL;
260   proto_tree *gen_tree = NULL;
261   proto_tree *entry = NULL;
262
263   if(tree) {
264     ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Generic Service");
265     gen_tree = proto_item_add_subtree(ti, ett_generic);
266   }
267         
268   if ((name = match_strval(aiminfo->subtype, aim_fnac_family_generic)) != NULL) {
269     if (ti)
270       proto_item_append_text(ti, ", %s", name);
271
272     if (check_col(pinfo->cinfo, COL_INFO))
273       col_add_fstr(pinfo->cinfo, COL_INFO, name);
274   }
275
276   switch(aiminfo->subtype)
277     {
278         case FAMILY_GENERIC_ERROR:
279            return dissect_aim_snac_error(tvb, pinfo, 0, gen_tree);
280         case FAMILY_GENERIC_CLIENTREADY:
281            ti = proto_tree_add_text(gen_tree, tvb, 0, -1, "Supported services");
282            entry = proto_item_add_subtree(ti, ett_generic_clientready);
283            while(tvb_reported_length_remaining(tvb, offset) > 0) {
284                         guint16 famnum = tvb_get_ntohs(tvb, offset);
285                         const char *famname = aim_get_familyname(famnum);
286                         proto_tree *subentry;
287                         ti = proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", famname?famname:"Unknown Family", famnum);
288                         offset+=2;
289                         
290                         subentry = proto_item_add_subtree(ti, ett_generic_clientready_item);
291
292                         proto_tree_add_text(subentry, tvb, offset, 2, "Version: %u", tvb_get_ntohs(tvb, offset) ); offset += 2;
293                         proto_tree_add_text(subentry, tvb, offset, 4, "DLL Version: %u", tvb_get_ntoh24(tvb, offset) ); offset += 4;
294           }
295           return offset;
296         case FAMILY_GENERIC_SERVERREADY:
297            ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Supported services");
298            entry = proto_item_add_subtree(ti, ett_generic_clientready);
299            while(tvb_length_remaining(tvb, offset) > 0) {
300                         guint16 famnum = tvb_get_ntohs(tvb, offset);
301                         const char *famname = aim_get_familyname(famnum);
302                         proto_tree_add_text(entry, tvb, offset, 2, "%s (0x%x)", famname?famname:"Unknown Family", famnum);
303                         offset+=2;
304           }
305           return offset;
306         case FAMILY_GENERIC_SERVICEREQ:
307           name = aim_get_familyname( tvb_get_ntohs(tvb, offset) );
308           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) );
309           offset+=2;
310           return offset;
311         case FAMILY_GENERIC_REDIRECT:
312           while(tvb_length_remaining(tvb, offset) > 0) {
313                 offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree);
314           }
315           return offset;
316         case FAMILY_GENERIC_CAPABILITIES:
317            ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Requested services");
318            entry = proto_item_add_subtree(ti, ett_generic_clientready);
319            while(tvb_length_remaining(tvb, offset) > 0) {
320                         guint16 famnum = tvb_get_ntohs(tvb, offset);
321                         const char *famname = aim_get_familyname(famnum);
322                         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));
323                         offset += 4;
324           }
325           return offset;
326         case FAMILY_GENERIC_CAPACK:
327            ti = proto_tree_add_text(gen_tree, tvb, offset, tvb_length_remaining(tvb, offset), "Accepted requested services");
328            entry = proto_item_add_subtree(ti, ett_generic_clientready);
329            while(tvb_length_remaining(tvb, offset) > 0) {
330                         guint16 famnum = tvb_get_ntohs(tvb, offset);
331                         const char *famname = aim_get_familyname(famnum);
332                         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));
333                         offset += 4;
334           }
335            return offset;
336
337
338     case FAMILY_GENERIC_MOTD: 
339           proto_tree_add_item(gen_tree, hf_generic_motd_motdtype, tvb, offset, 
340                           2, tvb_get_ntohs(tvb, offset));
341           offset+=2;
342           while(tvb_length_remaining(tvb, offset) > 0) {
343                 offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree);
344           }
345           return offset;
346
347         case FAMILY_GENERIC_RATEINFO:
348           return dissect_generic_rateinfo(tvb, pinfo, gen_tree);
349         case FAMILY_GENERIC_RATEINFOACK:
350           while(tvb_length_remaining(tvb, offset) > 0) {
351                   proto_tree_add_uint(gen_tree, hf_generic_rateinfoack_group, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
352                   offset+=2;
353           }
354           return offset;
355         case FAMILY_GENERIC_UNKNOWNx09:
356           /* Unknown: FIXME: */
357           return offset;
358         case FAMILY_GENERIC_RATECHANGE:
359           proto_tree_add_uint(gen_tree, hf_generic_ratechange_msg, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
360           offset+=2;
361           offset = dissect_rate_class(tvb, pinfo, offset, gen_tree);
362           break;
363           
364
365         case FAMILY_GENERIC_CLIENTPAUSEACK:
366           while(tvb_length_remaining(tvb, offset) > 0) {
367                         guint16 famnum = tvb_get_ntohs(tvb, offset);
368                         const char *famname = aim_get_familyname(famnum);
369                         proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", famname?famname:"Unknown Family", famnum);
370                         offset += 2;
371           }
372           return offset;
373         case FAMILY_GENERIC_SERVERRESUME:
374         case FAMILY_GENERIC_REQSELFINFO:
375         case FAMILY_GENERIC_NOP:
376         case FAMILY_GENERIC_SERVERPAUSE:
377         case FAMILY_GENERIC_RATEINFOREQ:
378           /* No data */
379           return offset;
380         case FAMILY_GENERIC_MIGRATIONREQ:
381           n = tvb_get_ntohs(tvb, offset);offset+=2;
382           proto_tree_add_uint(gen_tree, hf_generic_migration_numfams, tvb, offset, 2, n);
383           ti = proto_tree_add_text(gen_tree, tvb, offset, 2 * n, "Families to migrate");
384           entry = proto_item_add_subtree(ti, ett_generic_migratefamilies);
385           for(i = 0; i < n; i++) {
386                         guint16 famnum = tvb_get_ntohs(tvb, offset);
387                         const char *famname = aim_get_familyname(famnum);
388                         proto_tree_add_text(gen_tree, tvb, offset, 4, "Family: %s (0x%x)", famname?famname:"Unknown Family", famnum);
389                         offset += 2;
390           }
391
392           while(tvb_length_remaining(tvb, offset) > 0) {
393                 offset = dissect_aim_tlv(tvb, pinfo, offset, gen_tree);
394           }
395
396           return offset;
397         case FAMILY_GENERIC_SETPRIVFLAGS:
398           {
399                   guint32 flags = tvb_get_ntoh24(tvb, offset); 
400                   ti = proto_tree_add_uint(gen_tree, hf_generic_priv_flags, tvb, offset, 4, flags);
401                   entry = proto_item_add_subtree(ti, ett_generic_priv_flags);
402                   proto_tree_add_boolean(entry, hf_generic_allow_idle_see, tvb, offset, 4, flags);
403                   proto_tree_add_boolean(entry, hf_generic_allow_member_see, tvb, offset, 4, flags);
404                   offset+=4;
405           }
406           return offset;
407         case FAMILY_GENERIC_SELFINFO:
408         case FAMILY_GENERIC_EVIL:
409         case FAMILY_GENERIC_SETIDLE:
410         case FAMILY_GENERIC_SETSTATUS:
411         case FAMILY_GENERIC_WELLKNOWNURL:
412         case FAMILY_GENERIC_CLIENTVERREQ:
413         case FAMILY_GENERIC_CLIENTVERREPL:
414           /* FIXME */
415           return 0;
416         default: return 0;
417     }
418   return 0;
419 }
420
421 /* Register the protocol with Ethereal */
422 void
423 proto_register_aim_generic(void)
424 {
425
426 /* Setup list of header fields */
427   static hf_register_info hf[] = {
428         { &hf_generic_servicereq_service, 
429           { "Requested Service", "generic.servicereq.service", FT_UINT16,
430                   BASE_HEX, NULL, 0x0, "", HFILL },
431         },
432         { &hf_generic_motd_motdtype, 
433           { "MOTD Type", "generic.motd.motdtype", FT_UINT16,
434                   BASE_HEX, VALS(aim_snac_generic_motd_motdtypes), 0x0, "", HFILL },
435         },
436         { &hf_generic_rateinfo_numclasses,
437           { "Number of Rateinfo Classes", "aim.rateinfo.numclasses", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
438         },
439         { &hf_generic_rateinfo_windowsize,
440           { "Window Size", "aim.rateinfo.class.window_size", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
441         },
442         { &hf_generic_rateinfo_clearlevel,
443           { "Clear Level", "aim.rateinfo.class.clearlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
444         },
445         { &hf_generic_rateinfo_alertlevel,
446           { "Alert Level", "aim.rateinfo.class.alertlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
447         },
448         { &hf_generic_rateinfo_limitlevel,
449           { "Limit Level", "aim.rateinfo.class.limitlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
450         },
451         { &hf_generic_rateinfo_disconnectlevel,
452           { "Disconnect Level", "aim.rateinfo.class.disconnectlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
453         },
454         { &hf_generic_rateinfo_currentlevel,
455           { "Current Level", "aim.rateinfo.class.currentlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
456         },
457         { &hf_generic_rateinfo_maxlevel,
458       { "Max Level", "aim.rateinfo.class.maxlevel", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
459         },
460         { &hf_generic_rateinfo_lasttime,
461           { "Last Time", "aim.rateinfo.class.lasttime", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
462         },
463         { &hf_generic_rateinfo_curstate, 
464           { "Current State", "aim.rateinfo.class.curstate", FT_UINT8, BASE_HEX, VALS(rateinfo_states), 0x0, "", HFILL },
465         },
466         { &hf_generic_rateinfo_classid,
467           { "Class ID", "aim.rateinfo.class.id", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
468         },
469         { &hf_generic_rateinfo_numpairs,
470           { "Number of Family/Subtype pairs", "aim.rateinfo.class.numpairs", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
471         },
472         { &hf_generic_rateinfoack_group,
473           { "Acknowledged Rate Class", "aim.rateinfoack.class", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
474         },
475         { &hf_generic_ratechange_msg,
476           { "Rate Change Message", "aim.ratechange.msg", FT_UINT16, BASE_HEX, VALS(ratechange_msgs), 0x0, "", HFILL },
477         },
478         { &hf_generic_migration_numfams,
479           { "Number of families to migrate", "aim.migrate.numfams", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
480         },
481         { &hf_generic_priv_flags,
482           { "Privilege flags", "aim.privilege_flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
483         },
484         { &hf_generic_allow_idle_see,
485           { "Allow other users to see idle time", "aim.privilege_flags.allow_idle", FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x0001, "", HFILL },
486         },
487         { &hf_generic_allow_member_see,
488           { "Allow other users to see how long account has been a member", "aim.privilege_flags.allow_member", FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x0002, "", HFILL },
489         },
490   };
491
492 /* Setup protocol subtree array */
493   static gint *ett[] = {
494         &ett_generic,
495         &ett_generic_migratefamilies,
496         &ett_generic_rateinfo_class,
497         &ett_generic_rateinfo_group,
498         &ett_generic_rateinfo_groups,
499         &ett_generic_rateinfo_classes,
500         &ett_generic_clientready,
501         &ett_generic_clientready_item,
502         &ett_generic_serverready,
503         &ett_generic_priv_flags,
504   };
505
506 /* Register the protocol name and description */
507   proto_aim_generic = proto_register_protocol("AIM Generic Service", "AIM Generic", "aim_generic");
508
509 /* Required function calls to register the header fields and subtrees used */
510   proto_register_field_array(proto_aim_generic, hf, array_length(hf));
511   proto_register_subtree_array(ett, array_length(ett));
512 }
513
514 void
515 proto_reg_handoff_aim_generic(void)
516 {
517   dissector_handle_t aim_handle;
518   aim_handle = new_create_dissector_handle(dissect_aim_snac_generic, proto_aim_generic);
519   dissector_add("aim.family", FAMILY_GENERIC, aim_handle);
520   aim_init_family(FAMILY_GENERIC, "Generic", aim_fnac_family_generic);
521 }