3 * Routines for dissecting the America Online protocol
4 * Copyright (C) 2012 Tim Hentenaar <tim at hentenaar dot com>
6 * More information on the P3 frame protocol can be found on page 66 of:
7 * http://koin.org/files/aol.aim/aol/fdo/manuals/WAOL.doc
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/prefs.h>
16 #include <epan/expert.h>
18 #include "packet-tcp.h"
20 void proto_register_aol(void);
21 void proto_reg_handoff_aol(void);
23 static dissector_handle_t aol_handle
;
29 #define AOL_P3_FRAME_START 0x5a
30 #define AOL_P3_FRAME_END 0x0d
33 #define AOL_P3_TYPE_DATA 0x20
34 #define AOL_P3_TYPE_SS 0x21
35 #define AOL_P3_TYPE_SSR 0x22
36 #define AOL_P3_TYPE_INIT 0x23
37 #define AOL_P3_TYPE_ACK 0x24
38 #define AOL_P3_TYPE_NAK 0x25
39 #define AOL_P3_TYPE_HEARTBEAT 0x26
41 static const value_string aol_p3_types
[] = {
42 { AOL_P3_TYPE_DATA
, "Data" },
43 { AOL_P3_TYPE_SS
, "SS Request" },
44 { AOL_P3_TYPE_SSR
, "SS Response" },
45 { AOL_P3_TYPE_INIT
, "Init" },
46 { AOL_P3_TYPE_ACK
, "ACK" },
47 { AOL_P3_TYPE_NAK
, "NAK" },
48 { AOL_P3_TYPE_HEARTBEAT
, "Heartbeat" },
53 #define AOL_PLATFORM_WINDOWS 0x03
54 #define AOL_PLATFORM_MAC 0x0c
56 static const value_string aol_platforms
[] = {
57 { AOL_PLATFORM_WINDOWS
, "Microsoft Windows" },
58 { AOL_PLATFORM_MAC
, "Macintosh" },
62 /* Windows Memory Mode */
63 static const value_string aol_wmem_mode
[] = {
73 static int hf_aol_udata
;
74 static int hf_aol_init
;
77 static int hf_aol_start
;
78 static int hf_aol_crc
;
79 static int hf_aol_len
;
80 static int hf_aol_tx_seq
;
81 static int hf_aol_rx_seq
;
82 static int hf_aol_type
;
83 static int hf_aol_token
;
84 static int hf_aol_data
;
85 static int hf_aol_end
;
87 /* 'INIT' PDU Fields */
88 static int hf_aol_platform
;
89 static int hf_aol_version
;
90 static int hf_aol_subversion
;
91 static int hf_aol_unused
;
92 static int hf_aol_machine_mem
;
93 static int hf_aol_app_mem
;
94 static int hf_aol_pc_type
;
95 static int hf_aol_rel_month
;
96 static int hf_aol_rel_day
;
97 static int hf_aol_cust_class
;
98 static int hf_aol_udo_timestamp
;
99 static int hf_aol_dos_ver
;
100 static int hf_aol_sess_flags
;
101 static int hf_aol_video_type
;
102 static int hf_aol_cpu_type
;
103 static int hf_aol_media_type
;
104 static int hf_aol_win_ver
;
105 static int hf_aol_wmem_mode
;
106 static int hf_aol_horiz_res
;
107 static int hf_aol_vert_res
;
108 static int hf_aol_num_colors
;
109 static int hf_aol_filler
;
110 static int hf_aol_region
;
111 static int hf_aol_lang
;
112 static int hf_aol_conn_spd
;
116 static int ett_aol_data
;
118 static expert_field ei_aol_pdu_length_bad
;
119 static expert_field ei_aol_end_missing
;
122 static bool aol_desegment
= true;
125 * Dissect the 'INIT' PDU.
127 static unsigned dissect_aol_init(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, unsigned offset
, proto_tree
*tree
) {
128 proto_item
*data_item
;
129 proto_tree
*data_tree
;
130 uint16_t dos_ver
= 0;
131 uint16_t win_ver
= 0;
133 /* Add the Data subtree */
134 data_item
= proto_tree_add_item(tree
,hf_aol_init
,tvb
,offset
,tvb_reported_length_remaining(tvb
,offset
)-1,ENC_NA
);
135 data_tree
= proto_item_add_subtree(data_item
,ett_aol_data
);
137 /* Now, parse the structure */
138 proto_tree_add_item(data_tree
,hf_aol_platform
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
139 proto_tree_add_item(data_tree
,hf_aol_version
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
140 proto_tree_add_item(data_tree
,hf_aol_subversion
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
141 proto_tree_add_item(data_tree
,hf_aol_unused
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
142 proto_tree_add_item(data_tree
,hf_aol_machine_mem
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
143 proto_tree_add_item(data_tree
,hf_aol_app_mem
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
144 proto_tree_add_item(data_tree
,hf_aol_pc_type
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2;
145 proto_tree_add_item(data_tree
,hf_aol_rel_month
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
146 proto_tree_add_item(data_tree
,hf_aol_rel_day
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
147 proto_tree_add_item(data_tree
,hf_aol_cust_class
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2;
148 proto_tree_add_item(data_tree
,hf_aol_udo_timestamp
,tvb
,offset
,4,ENC_LITTLE_ENDIAN
); offset
+= 4;
150 dos_ver
= tvb_get_ntohs(tvb
,offset
);
151 proto_tree_add_uint_format_value(data_tree
,hf_aol_dos_ver
,tvb
,offset
,2,dos_ver
,"%d.%d",(dos_ver
& 0xFF00) >> 8,dos_ver
& 0xFF);
154 proto_tree_add_item(data_tree
,hf_aol_sess_flags
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2;
155 proto_tree_add_item(data_tree
,hf_aol_video_type
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
156 proto_tree_add_item(data_tree
,hf_aol_cpu_type
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
157 proto_tree_add_item(data_tree
,hf_aol_media_type
, tvb
,offset
,4,ENC_LITTLE_ENDIAN
); offset
+= 4;
159 /* Windows version is a 32-bit value, but only the lower 16 bits are populated */
160 win_ver
= tvb_get_ntohs(tvb
,offset
);
161 proto_tree_add_uint_format_value(data_tree
,hf_aol_win_ver
,tvb
,offset
,2,dos_ver
,"%d.%d",(win_ver
& 0xFF00) >> 8,win_ver
& 0xFF);
164 proto_tree_add_item(data_tree
,hf_aol_wmem_mode
, tvb
,offset
,1,ENC_NA
); offset
+= 1;
165 proto_tree_add_item(data_tree
,hf_aol_horiz_res
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2;
166 proto_tree_add_item(data_tree
,hf_aol_vert_res
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2;
167 proto_tree_add_item(data_tree
,hf_aol_num_colors
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2; /* 37b */
169 /* WAOL 1.5 (48b), >= 2.5 (49b) */
170 if (tvb_reported_length_remaining(tvb
,offset
) <= 13) { /* WAOL 1.5 - 3.0 */
171 if (tvb_reported_length_remaining(tvb
,offset
) == 13) { /* WAOL > 1.5 */
172 proto_tree_add_item(data_tree
,hf_aol_filler
,tvb
,offset
,1,ENC_BIG_ENDIAN
); offset
+= 1;
175 proto_tree_add_item(data_tree
,hf_aol_region
, tvb
,offset
,2,ENC_LITTLE_ENDIAN
); offset
+= 2;
176 proto_tree_add_item(data_tree
,hf_aol_lang
, tvb
,offset
,8,ENC_LITTLE_ENDIAN
); offset
+= 8;
177 proto_tree_add_item(data_tree
,hf_aol_conn_spd
,tvb
,offset
,1,ENC_NA
); offset
+= 1;
178 } else { /* WAOL >= 4.0 - ??? (52b) */
186 * Get the length of a particular PDU (+6 bytes for the frame)
188 static unsigned get_aol_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
189 int offset
, void *data _U_
)
193 /* Get the PDU length */
194 plen
= tvb_get_ntohs(tvb
,offset
+3);
201 static int dissect_aol_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
) {
203 proto_tree
*aol_tree
;
206 uint8_t pdu_type
= 0;
208 /* Set the protocol name, and info column text. */
209 col_set_str(pinfo
->cinfo
,COL_PROTOCOL
,"AOL");
210 col_set_str(pinfo
->cinfo
,COL_INFO
,"America Online");
212 /* Add our tree item, and tree */
213 ti
= proto_tree_add_item(tree
,proto_aol
,tvb
,0,-1,ENC_NA
);
214 aol_tree
= proto_item_add_subtree(ti
,ett_aol
);
215 pdu_len
= tvb_get_ntohs(tvb
,3);
217 /* Add the first few P3 fields */
218 proto_tree_add_item(aol_tree
,hf_aol_start
,tvb
,offset
,1,ENC_NA
); offset
+= 1;
219 proto_tree_add_checksum(aol_tree
, tvb
, offset
, hf_aol_crc
, -1, NULL
, pinfo
, 0, ENC_BIG_ENDIAN
, PROTO_CHECKSUM_NO_FLAGS
); offset
+= 2;
220 proto_tree_add_item(aol_tree
,hf_aol_len
, tvb
,offset
,2,ENC_BIG_ENDIAN
); offset
+= 2;
222 /* Add sequence fields */
224 proto_tree_add_item(aol_tree
,hf_aol_tx_seq
,tvb
,offset
,1,ENC_NA
); offset
+= 1;
225 proto_tree_add_item(aol_tree
,hf_aol_rx_seq
,tvb
,offset
,1,ENC_NA
); offset
+= 1;
229 /* Add type (and add it to the tree item / info column) */
231 pdu_type
= tvb_get_uint8(tvb
,offset
) & 0x3f;
232 col_append_fstr(pinfo
->cinfo
,COL_INFO
," [Type: %s]",val_to_str_const(pdu_type
,aol_p3_types
,"Unknown"));
233 proto_item_append_text(ti
," [Type: %s]",val_to_str_const(pdu_type
,aol_p3_types
,"Unknown"));
234 proto_tree_add_uint(aol_tree
,hf_aol_type
,tvb
,offset
,1,pdu_type
);
235 offset
+= 1; pdu_len
-= 1;
238 /* Now for the data... */
240 unsigned old_offset
= offset
;
242 if (tvb_reported_length_remaining(tvb
,offset
) > pdu_len
) {
243 /* Init packets are a special case */
244 if (pdu_type
== AOL_P3_TYPE_INIT
) {
245 offset
= dissect_aol_init(tvb
,pinfo
,offset
,aol_tree
);
248 const uint8_t* token
;
250 proto_tree_add_item_ret_string(aol_tree
,hf_aol_token
,tvb
,offset
,2,ENC_ASCII
,pinfo
->pool
,&token
);
252 col_append_fstr(pinfo
->cinfo
,COL_INFO
," [Token: '%s']", token
);
253 proto_item_append_text(ti
," [Token: '%s']", token
);
254 offset
+= 2; pdu_len
-= 2;
259 proto_tree_add_item(aol_tree
,hf_aol_data
,tvb
,offset
,pdu_len
,ENC_NA
);
264 if (offset
< (old_offset
+ pdu_len
)) {
265 /* We didn't parse the entire pdu... */
266 proto_tree_add_item(aol_tree
,hf_aol_udata
,tvb
,offset
,(old_offset
+pdu_len
)-offset
,ENC_NA
);
267 offset
= old_offset
+ pdu_len
;
270 /* Malformed packet */
271 expert_add_info(pinfo
,ti
,&ei_aol_pdu_length_bad
);
275 /* End-of-Frame Marker */
276 if (tvb_reported_length_remaining(tvb
,offset
) >= 1) {
277 proto_tree_add_item(aol_tree
,hf_aol_end
,tvb
,offset
,1,ENC_NA
);/* offset += 1;*/
279 /* Malformed Packet */
280 expert_add_info(pinfo
,ti
,&ei_aol_end_missing
);
283 return tvb_reported_length(tvb
);
289 static int dissect_aol(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
) {
290 /* Ensure this really is an AOL packet */
291 if (tvb_reported_length(tvb
) >= 1 && tvb_get_uint8(tvb
,0) != AOL_P3_FRAME_START
) return 0;
294 tcp_dissect_pdus(tvb
,pinfo
,tree
,aol_desegment
,9,get_aol_pdu_len
,dissect_aol_pdu
,data
);
295 return tvb_reported_length(tvb
);
299 * Protocol Registration Routine
301 * Registers our protocol.
303 void proto_register_aol(void) {
305 static hf_register_info hf
[] = {
307 { &hf_aol_udata
, { "Unparsed Data", "aol.udata", FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
308 { &hf_aol_init
, { "AOL 'INIT' Data", "aol.init_data",FT_NONE
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
311 { &hf_aol_start
, { "Start of Frame", "aol.start", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
312 { &hf_aol_crc
, { "Checksum", "aol.checksum", FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
313 { &hf_aol_len
, { "Length", "aol.len", FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
314 { &hf_aol_tx_seq
, { "Tx Sequence", "aol.tx_seq", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
315 { &hf_aol_rx_seq
, { "Rx Sequence", "aol.rx_seq", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
316 { &hf_aol_type
, { "Type", "aol.type", FT_UINT8
, BASE_HEX
, VALS(aol_p3_types
), 0x00, NULL
, HFILL
}},
317 { &hf_aol_token
, { "Token", "aol.token", FT_STRING
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
318 { &hf_aol_data
, { "Data", "aol.data", FT_BYTES
, BASE_NONE
, NULL
, 0x00, NULL
, HFILL
}},
319 { &hf_aol_end
, { "End of Frame", "aol.end", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
322 { &hf_aol_platform
, { "Platform", "aol.init.platform", FT_UINT8
, BASE_HEX
, VALS(aol_platforms
),0x00, NULL
, HFILL
}},
323 { &hf_aol_version
, { "Client Version", "aol.init.version", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
324 { &hf_aol_subversion
, { "Client Subversion","aol.init.subversion", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
325 { &hf_aol_unused
, { "Unused", "aol.init.unused", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
326 { &hf_aol_machine_mem
, { "Machine Memory", "aol.init.memory", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
327 { &hf_aol_app_mem
, { "App Memory", "aol.init.app_memory", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
328 { &hf_aol_pc_type
, { "PC Type", "aol.init.pc_type", FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
329 { &hf_aol_rel_month
, { "Release Month", "aol.init.rel_month", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
330 { &hf_aol_rel_day
, { "Release Day", "aol.init.rel_day", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
331 { &hf_aol_cust_class
, { "Customer Class", "aol.init.cust_class", FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
332 { &hf_aol_udo_timestamp
,{ "UDO Timestamp", "aol.init.udo_ts", FT_UINT32
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
333 { &hf_aol_dos_ver
, { "DOS Version", "aol.init.dos_ver", FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
334 { &hf_aol_sess_flags
, { "Session Flags", "aol.init.sess_flags", FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
335 { &hf_aol_video_type
, { "Video Type", "aol.init.video_type", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
336 { &hf_aol_cpu_type
, { "CPU Type", "aol.init.cpu_type", FT_UINT8
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
337 { &hf_aol_media_type
, { "Media Type", "aol.init.media_type", FT_UINT32
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
338 { &hf_aol_win_ver
, { "Windows Version", "aol.init.win_ver", FT_UINT32
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
339 { &hf_aol_wmem_mode
, { "Windows Mem Type", "aol.init.wmem_mode", FT_UINT8
, BASE_DEC
, VALS(aol_wmem_mode
),0x00, NULL
, HFILL
}},
340 { &hf_aol_horiz_res
, { "Horizontal Res", "aol.init.horiz_res", FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
341 { &hf_aol_vert_res
, { "Vertical Res", "aol.init.vert_res", FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
342 { &hf_aol_num_colors
, { "Colors", "aol.init.colors", FT_UINT16
, BASE_DEC
, NULL
, 0x00, NULL
, HFILL
}},
343 { &hf_aol_filler
, { "Filler Byte", "aol.init.filler", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
344 { &hf_aol_region
, { "AOL Region", "aol.init.region", FT_UINT16
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
345 { &hf_aol_lang
, { "AOL Language(s)", "aol.init.langs", FT_UINT64
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
346 { &hf_aol_conn_spd
, { "Connection Speed", "aol.init.conn_spd", FT_UINT8
, BASE_HEX
, NULL
, 0x00, NULL
, HFILL
}},
350 static int *ett
[] = {
355 static ei_register_info ei
[] = {
356 { &ei_aol_pdu_length_bad
, { "aol.pdu_length_bad", PI_MALFORMED
, PI_ERROR
, "pdu length > tvb length", EXPFILL
}},
357 { &ei_aol_end_missing
, { "aol.end_missing", PI_PROTOCOL
, PI_WARN
, "End of frame marker expected", EXPFILL
}},
360 /* Module (for prefs) */
361 module_t
*aol_module
;
362 expert_module_t
* expert_aol
;
364 /* Register the protocol and header fields */
365 proto_aol
= proto_register_protocol("America Online","AOL","aol");
366 proto_register_field_array(proto_aol
,hf
,array_length(hf
));
367 proto_register_subtree_array(ett
,array_length(ett
));
369 expert_aol
= expert_register_protocol(proto_aol
);
370 expert_register_field_array(expert_aol
, ei
, array_length(ei
));
373 aol_module
= prefs_register_protocol(proto_aol
,NULL
);
374 prefs_register_bool_preference(aol_module
,"desegment",
375 "Reassemble AOL messages spanning multiple TCP segments",
376 "Whether the AOL dissector should reassemble messages spanning multiple TCP segments. "
377 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" "
378 "in the TCP protocol settings.",&aol_desegment
);
380 /* Register the dissector */
381 aol_handle
= register_dissector("aol", dissect_aol
,proto_aol
);
385 * Dissector Handoff Routine
387 * Initialize the dissector.
389 void proto_reg_handoff_aol(void) {
390 dissector_add_uint_with_preference("tcp.port",AOL_PORT
,aol_handle
);
396 * Editor modelines - https://www.wireshark.org/tools/modelines.html
401 * indent-tabs-mode: t
404 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
405 * :indentSize=8:tabSize=8:noTabs=false: