add details for doxygen
[obnox/wireshark/wip.git] / packet-aim-messaging.c
1 /* packet-aim-messaging.c
2  * Routines for AIM Instant Messenger (OSCAR) dissection, SNAC Messaging
3  * Copyright 2004, Jelmer Vernooij <jelmer@samba.org>
4  * Copyright 2000, Ralf Hoelzer <ralf@well.com>
5  * Copyright 2004, Devin Heitmueller <dheitmueller@netilla.com>
6  *
7  * $Id: packet-aim-messaging.c,v 1.9 2004/06/03 04:19:38 guy Exp $
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@ethereal.com>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36
37 #include <glib.h>
38
39 #include <epan/packet.h>
40 #include <epan/strutil.h>
41
42 #include "packet-aim.h"
43
44 #define FAMILY_MESSAGING  0x0004
45
46 /* Family Messaging Service */
47 #define FAMILY_MESSAGING_ERROR          0x0001
48 #define FAMILY_MESSAGING_SETICBMPARAM   0x0002
49 #define FAMILY_MESSAGING_RESETICBMPARAM 0x0003
50 #define FAMILY_MESSAGING_REQPARAMINFO   0x0004
51 #define FAMILY_MESSAGING_PARAMINFO      0x0005
52 #define FAMILY_MESSAGING_OUTGOING       0x0006
53 #define FAMILY_MESSAGING_INCOMING       0x0007
54 #define FAMILY_MESSAGING_EVILREQ                0x0008
55 #define FAMILY_MESSAGING_EVIL           0x0009
56 #define FAMILY_MESSAGING_MISSEDCALL     0x000a
57 #define FAMILY_MESSAGING_CLIENTAUTORESP 0x000b
58 #define FAMILY_MESSAGING_ACK            0x000c
59 #define FAMILY_MESSAGING_MINITYPING     0x0014
60 #define FAMILY_MESSAGING_DEFAULT        0xffff
61
62 static const value_string aim_fnac_family_messaging[] = {
63   { FAMILY_MESSAGING_ERROR, "Error" },
64   { FAMILY_MESSAGING_SETICBMPARAM, "Set ICBM Parameter" },
65   { FAMILY_MESSAGING_RESETICBMPARAM, "Reset ICBM Parameter" },
66   { FAMILY_MESSAGING_REQPARAMINFO, "Request Parameter Info" },
67   { FAMILY_MESSAGING_PARAMINFO, "Parameter Info" },
68   { FAMILY_MESSAGING_INCOMING, "Incoming" },
69   { FAMILY_MESSAGING_OUTGOING, "Outgoing" },
70   { FAMILY_MESSAGING_EVILREQ, "Evil Request" },
71   { FAMILY_MESSAGING_EVIL, "Evil Response" },
72   { FAMILY_MESSAGING_MISSEDCALL, "Missed Call" },
73   { FAMILY_MESSAGING_CLIENTAUTORESP, "Client Auto Response" },
74   { FAMILY_MESSAGING_ACK, "Acknowledge" },
75   { FAMILY_MESSAGING_MINITYPING, "Mini Typing Notifications (MTN)" },
76   { FAMILY_MESSAGING_DEFAULT, "Messaging Default" },
77   { 0, NULL }
78 };
79
80
81 #define INCOMING_CH1_MESSAGE_BLOCK     0x0002
82 #define INCOMING_CH1_SERVER_ACK_REQ    0x0003
83 #define INCOMING_CH1_MESSAGE_AUTH_RESP 0x0004
84 #define INCOMING_CH1_MESSAGE_OFFLINE   0x0006
85 #define INCOMING_CH1_ICON_PRESENT      0x0008
86 #define INCOMING_CH1_BUDDY_REQ         0x0009
87 #define INCOMING_CH1_TYPING            0x000b
88
89 static const aim_tlv messaging_incoming_ch1_tlvs[] = {
90   { INCOMING_CH1_MESSAGE_BLOCK, "Message Block", dissect_aim_tlv_value_messageblock },
91   { INCOMING_CH1_SERVER_ACK_REQ, "Server Ack Requested", dissect_aim_tlv_value_bytes },
92   { INCOMING_CH1_MESSAGE_AUTH_RESP, "Message is Auto Response", dissect_aim_tlv_value_bytes },
93   { INCOMING_CH1_MESSAGE_OFFLINE, "Message was received offline", dissect_aim_tlv_value_bytes },
94   { INCOMING_CH1_ICON_PRESENT, "Icon present", dissect_aim_tlv_value_bytes },
95   { INCOMING_CH1_BUDDY_REQ, "Buddy Req", dissect_aim_tlv_value_bytes },
96   { INCOMING_CH1_TYPING, "Non-direct connect typing notification", dissect_aim_tlv_value_bytes },
97   { 0, "Unknown", NULL }
98 };
99
100 #define MINITYPING_FINISHED_SIGN                        0x0000
101 #define MINITYPING_TEXT_TYPED_SIGN                      0x0001
102 #define MINITYPING_BEGUN_SIGN                           0x0002
103
104 static const value_string minityping_type[] = {
105         {MINITYPING_FINISHED_SIGN, "Typing finished sign" },
106         {MINITYPING_TEXT_TYPED_SIGN, "Text typed sign" },
107         {MINITYPING_BEGUN_SIGN, "Typing begun sign" },
108         {0, NULL }
109 };
110
111 #define EVIL_ORIGIN_ANONYMOUS           1
112 #define EVIL_ORIGIN_NONANONYMOUS        2
113
114 static const value_string evil_origins[] = {
115         {EVIL_ORIGIN_ANONYMOUS, "Anonymous"},
116         {EVIL_ORIGIN_NONANONYMOUS, "Non-Anonymous"},
117         {0, NULL },
118 };
119
120 /* Initialize the protocol and registered fields */
121 static int proto_aim_messaging = -1;
122 static int hf_aim_icbm_channel = -1;
123 static int hf_aim_icbm_cookie = -1;
124 static int hf_aim_icbm_msg_flags = -1;
125 static int hf_aim_icbm_max_sender_warnlevel = -1;
126 static int hf_aim_icbm_max_receiver_warnlevel = -1;
127 static int hf_aim_icbm_max_snac_size = -1;
128 static int hf_aim_icbm_min_msg_interval = -1;
129 static int hf_aim_icbm_unknown = -1;
130 static int hf_aim_icbm_notification_cookie = -1;
131 static int hf_aim_icbm_notification_channel = -1;
132 static int hf_aim_icbm_notification_type = -1;
133 static int hf_aim_message_channel_id = -1;
134 static int hf_aim_icbm_evil = -1;
135 static int hf_aim_evil_warn_level = -1;
136 static int hf_aim_evil_new_warn_level = -1;
137
138 /* Initialize the subtree pointers */
139 static gint ett_aim_messaging = -1;
140
141 static int dissect_aim_messaging(tvbuff_t *tvb, packet_info *pinfo, 
142                                        proto_tree *tree)
143 {
144   guint8 buddyname_length = 0;
145   char buddyname[MAX_BUDDYNAME_LENGTH + 1];
146   gint msg_length;
147   guchar msg[1000];
148   int offset = 0;
149   struct aiminfo *aiminfo = pinfo->private_data;
150   proto_item *ti = NULL;
151   proto_tree *msg_tree = NULL;
152   
153   if(tree) {
154     ti = proto_tree_add_text(tree, tvb, 0, -1,"AIM Messaging Service");
155     msg_tree = proto_item_add_subtree(ti, ett_aim_messaging);
156   }
157
158   switch(aiminfo->subtype)
159     {    
160     case FAMILY_MESSAGING_ERROR:
161       return dissect_aim_snac_error(tvb, pinfo, offset, msg_tree);
162     case FAMILY_MESSAGING_RESETICBMPARAM:
163     case FAMILY_MESSAGING_REQPARAMINFO:
164       /* No data */
165       return 0;
166     case FAMILY_MESSAGING_OUTGOING:
167
168       /* ICBM Cookie */
169       proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
170       offset += 8;
171
172       /* Message Channel ID */
173       proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
174                           FALSE);
175       offset += 2;
176
177       /* Add the outgoing username to the info column */
178       if (check_col(pinfo->cinfo, COL_INFO)) {
179         buddyname_length = aim_get_buddyname(buddyname, tvb, offset, 
180                                              offset + 1);
181         col_append_fstr(pinfo->cinfo, COL_INFO, " to: %s", buddyname);
182       }
183
184       offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
185
186       while(tvb_reported_length_remaining(tvb, offset) > 0) {
187         /* djh - Note that we reuse the "incoming ch1 tlv" set even though this
188            is outgoing.  We may need to split this to a separate TLV set, but
189            so far I haven't seen the need @@@@@@@@ */
190         offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree, 
191                                           messaging_incoming_ch1_tlvs);
192       }
193
194       return offset;
195       
196     case FAMILY_MESSAGING_INCOMING:
197
198       /* ICBM Cookie */
199       proto_tree_add_item(msg_tree, hf_aim_icbm_cookie, tvb, offset, 8, FALSE);
200       offset += 8;
201
202       /* Message Channel ID */
203       proto_tree_add_item(msg_tree, hf_aim_message_channel_id, tvb, offset, 2,
204                           FALSE);
205       offset += 2;
206
207       offset = dissect_aim_userinfo(tvb, pinfo, offset, msg_tree);
208           
209       while(tvb_reported_length_remaining(tvb, offset) > 0) {
210         offset = dissect_aim_tlv(tvb, pinfo, offset, msg_tree, 
211                                           messaging_incoming_ch1_tlvs);
212       }
213       
214       return offset;
215     case FAMILY_MESSAGING_SETICBMPARAM:
216     case FAMILY_MESSAGING_PARAMINFO:
217       proto_tree_add_item(msg_tree, hf_aim_icbm_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
218       proto_tree_add_item(msg_tree, hf_aim_icbm_msg_flags, tvb, offset, 4, tvb_get_ntoh24(tvb, offset)); offset+=4;
219       proto_tree_add_item(msg_tree, hf_aim_icbm_max_snac_size, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
220       proto_tree_add_item(msg_tree, hf_aim_icbm_max_sender_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
221       proto_tree_add_item(msg_tree, hf_aim_icbm_max_receiver_warnlevel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
222       proto_tree_add_item(msg_tree, hf_aim_icbm_min_msg_interval, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
223       proto_tree_add_item(msg_tree, hf_aim_icbm_unknown, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
224       return offset;
225     case FAMILY_MESSAGING_EVILREQ:
226       proto_tree_add_item(msg_tree, hf_aim_icbm_evil, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
227       return dissect_aim_buddyname(tvb, pinfo, offset, tree);
228     case FAMILY_MESSAGING_EVIL:
229       proto_tree_add_item(msg_tree, hf_aim_evil_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
230       proto_tree_add_item(msg_tree, hf_aim_evil_new_warn_level, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
231       return offset;
232     case FAMILY_MESSAGING_MINITYPING:
233       proto_tree_add_item(msg_tree,hf_aim_icbm_notification_cookie, tvb, offset, 8, FALSE); offset+=8;
234       proto_tree_add_item(msg_tree,hf_aim_icbm_notification_channel, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
235       offset = dissect_aim_buddyname(tvb, pinfo, offset, msg_tree);
236       proto_tree_add_item(msg_tree,hf_aim_icbm_notification_type, tvb, offset, 2, tvb_get_ntohs(tvb, offset)); offset+=2;
237       return offset;
238     case FAMILY_MESSAGING_MISSEDCALL:
239     case FAMILY_MESSAGING_CLIENTAUTORESP:
240     case FAMILY_MESSAGING_ACK:
241       /*FIXME*/
242
243
244     default:
245       return 0;
246     }
247 }
248
249 /* Register the protocol with Ethereal */
250 void
251 proto_register_aim_messaging(void)
252 {
253
254 /* Setup list of header fields */
255   static hf_register_info hf[] = {
256     { &hf_aim_icbm_channel,
257       { "Channel to setup", "aim.icbm.channel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
258     },
259     { &hf_aim_icbm_msg_flags, 
260       { "Message Flags", "aim.icbm.flags", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL },
261     },
262     { &hf_aim_icbm_max_snac_size,
263       { "Max SNAC Size", "aim.icbm.max_snac", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
264     },
265     { &hf_aim_icbm_max_sender_warnlevel,
266       { "Max sender warn level", "aim.icbm.max_sender_warn-level", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
267     },
268     { &hf_aim_icbm_max_receiver_warnlevel,
269       { "max receiver warn level", "aim.icbm.max_receiver_warnlevel", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
270     },
271     { &hf_aim_icbm_min_msg_interval,
272       { "Minimum message interval (seconds)", "aim.icbm.min_msg_interval", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
273     },
274     { &hf_aim_icbm_unknown,
275       { "Unknown parameter", "aim.icbm.unknown", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL },
276     },
277     { &hf_aim_icbm_cookie,
278       { "ICBM Cookie", "aim.messaging.icbmcookie", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL }
279     },
280     { &hf_aim_message_channel_id,
281       { "Message Channel ID", "aim.messaging.channelid", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }
282     },
283     { &hf_aim_icbm_evil,
284       { "Send Evil Bit As", "aim.evilreq.origin", FT_UINT16, BASE_DEC, VALS(evil_origins), 0x0, "", HFILL },
285     },
286     { &hf_aim_evil_warn_level,
287       { "Old warning level", "aim.evil.warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
288     },
289     { &hf_aim_evil_new_warn_level,
290       { "New warning level", "aim.evil.new_warn_level", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
291     },
292     { &hf_aim_icbm_notification_cookie,
293       { "Notification Cookie", "aim.notification.cookie", FT_BYTES, BASE_DEC, NULL, 0x0, "", HFILL },
294     },
295     { &hf_aim_icbm_notification_channel,
296       { "Notification Channel", "aim.notification.channel", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
297     },
298     { &hf_aim_icbm_notification_type,
299       { "Notification Type", "aim.notification.type", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL },
300     },
301   };
302
303 /* Setup protocol subtree array */
304   static gint *ett[] = {
305     &ett_aim_messaging,
306   };
307
308 /* Register the protocol name and description */
309   proto_aim_messaging = proto_register_protocol("AIM Messaging", "AIM Messaging", "aim_messaging");
310
311 /* Required function calls to register the header fields and subtrees used */
312   proto_register_field_array(proto_aim_messaging, hf, array_length(hf));
313   proto_register_subtree_array(ett, array_length(ett));
314 }
315
316 void
317 proto_reg_handoff_aim_messaging(void)
318 {
319   dissector_handle_t aim_handle;
320
321   aim_handle = new_create_dissector_handle(dissect_aim_messaging, proto_aim_messaging);
322   dissector_add("aim.family", FAMILY_MESSAGING, aim_handle);
323   aim_init_family(FAMILY_MESSAGING, "Messaging", aim_fnac_family_messaging);
324 }