wireshark/epan/dissectors/packet-aol.c
Michael Mann 268841f3e0 Combine Decode As and port preferences for tcp.port dissector table.
This patch introduces new APIs to allow dissectors to have a preference for
a (TCP) port, but the underlying data is actually part of Decode As functionality.
For now the APIs are intentionally separate from the regular APIs that register a
dissector within a dissector table.  It may be possible to eventually combine the
two so that all dissectors that register with a dissector table have an opportunity
to "automatically" have a preference to adjust the "table value" through the
preferences dialog.

The tcp.port dissector table was used as the guinea pig.  This will eventually be
expanded to other dissector tables as well (most notably UDP ports).  Some
dissectors that "shared" a TCP/UDP port preference were also converted. It also
removed the need for some preference callback functions (mostly when the callback
function was the proto_reg_handoff function) so there is cleanup around that.

Dissectors that has a port preference whose default was 0 were switched to using
the dissector_add_for_decode_as_with_preference API rather than dissector_add_uint_with_preference

Also added comments for TCP ports used that aren't IANA registered.

Change-Id: I99604f95d426ad345f4b494598d94178b886eb67
Reviewed-on: https://code.wireshark.org/review/17724
Reviewed-by: Michael Mann <mmann78@netscape.net>
2016-10-08 02:44:53 +00:00

419 lines
18 KiB
C

/* packet-aol.c
*
* Routines for dissecting the America Online protocol
* Copyright (C) 2012 Tim Hentenaar <tim at hentenaar dot com>
*
* More information on the P3 frame protocol can be found on page 66 of:
* http://koin.org/files/aol.aim/aol/fdo/manuals/WAOL.doc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "config.h"
#include <epan/packet.h>
#include <epan/prefs.h>
#include <epan/expert.h>
#include "packet-tcp.h"
void proto_register_aol(void);
void proto_reg_handoff_aol(void);
/* AOL's port */
#define AOL_PORT 5190
/* Frame markers */
#define AOL_P3_FRAME_START 0x5a
#define AOL_P3_FRAME_END 0x0d
/* Frame types */
#define AOL_P3_TYPE_DATA 0x20
#define AOL_P3_TYPE_SS 0x21
#define AOL_P3_TYPE_SSR 0x22
#define AOL_P3_TYPE_INIT 0x23
#define AOL_P3_TYPE_ACK 0x24
#define AOL_P3_TYPE_NAK 0x25
#define AOL_P3_TYPE_HEARTBEAT 0x26
static const value_string aol_p3_types[] = {
{ AOL_P3_TYPE_DATA, "Data" },
{ AOL_P3_TYPE_SS, "SS Request" },
{ AOL_P3_TYPE_SSR, "SS Response" },
{ AOL_P3_TYPE_INIT, "Init" },
{ AOL_P3_TYPE_ACK, "ACK" },
{ AOL_P3_TYPE_NAK, "NAK" },
{ AOL_P3_TYPE_HEARTBEAT, "Heartbeat" },
{ 0, NULL }
};
/* Platforms */
#define AOL_PLATFORM_WINDOWS 0x03
#define AOL_PLATFORM_MAC 0x0c
static const value_string aol_platforms[] = {
{ AOL_PLATFORM_WINDOWS, "Microsoft Windows" },
{ AOL_PLATFORM_MAC, "Macintosh" },
{ 0, NULL }
};
/* Windows Memory Mode */
static const value_string aol_wmem_mode[] = {
{ 0, "Standard" },
{ 1, "Enhanced" },
{ 0, NULL }
};
/* Protocol */
static int proto_aol = -1;
/* Special fields */
static int hf_aol_udata = -1;
static int hf_aol_init = -1;
/* Header fields */
static int hf_aol_start = -1;
static int hf_aol_crc = -1;
static int hf_aol_len = -1;
static int hf_aol_tx_seq = -1;
static int hf_aol_rx_seq = -1;
static int hf_aol_type = -1;
static int hf_aol_token = -1;
static int hf_aol_data = -1;
static int hf_aol_end = -1;
/* 'INIT' PDU Fields */
static int hf_aol_platform = -1;
static int hf_aol_version = -1;
static int hf_aol_subversion = -1;
static int hf_aol_unused = -1;
static int hf_aol_machine_mem = -1;
static int hf_aol_app_mem = -1;
static int hf_aol_pc_type = -1;
static int hf_aol_rel_month = -1;
static int hf_aol_rel_day = -1;
static int hf_aol_cust_class = -1;
static int hf_aol_udo_timestamp = -1;
static int hf_aol_dos_ver = -1;
static int hf_aol_sess_flags = -1;
static int hf_aol_video_type = -1;
static int hf_aol_cpu_type = -1;
static int hf_aol_media_type = -1;
static int hf_aol_win_ver = -1;
static int hf_aol_wmem_mode = -1;
static int hf_aol_horiz_res = -1;
static int hf_aol_vert_res = -1;
static int hf_aol_num_colors = -1;
static int hf_aol_filler = -1;
static int hf_aol_region = -1;
static int hf_aol_lang = -1;
static int hf_aol_conn_spd = -1;
/* Subtrees */
static int ett_aol = -1;
static int ett_aol_data = -1;
static expert_field ei_aol_pdu_length_bad = EI_INIT;
static expert_field ei_aol_end_missing = EI_INIT;
/* Prefs */
static gboolean aol_desegment = TRUE;
/**
* Dissect the 'INIT' PDU.
*/
static guint dissect_aol_init(tvbuff_t *tvb, packet_info *pinfo _U_, guint offset, proto_tree *tree) {
proto_item *data_item;
proto_tree *data_tree;
guint16 dos_ver = 0;
guint16 win_ver = 0;
/* Add the Data subtree */
data_item = proto_tree_add_item(tree,hf_aol_init,tvb,offset,tvb_reported_length_remaining(tvb,offset)-1,ENC_NA);
data_tree = proto_item_add_subtree(data_item,ett_aol_data);
/* Now, parse the structure */
proto_tree_add_item(data_tree,hf_aol_platform, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_version, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_subversion, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_unused, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_machine_mem, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_app_mem, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_pc_type, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
proto_tree_add_item(data_tree,hf_aol_rel_month, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_rel_day, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_cust_class, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
proto_tree_add_item(data_tree,hf_aol_udo_timestamp,tvb,offset,4,ENC_LITTLE_ENDIAN); offset += 4;
dos_ver = tvb_get_ntohs(tvb,offset);
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);
offset += 2;
proto_tree_add_item(data_tree,hf_aol_sess_flags, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
proto_tree_add_item(data_tree,hf_aol_video_type, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_cpu_type, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_media_type, tvb,offset,4,ENC_LITTLE_ENDIAN); offset += 4;
/* Windows version is a 32-bit value, but only the lower 16 bits are populated */
win_ver = tvb_get_ntohs(tvb,offset);
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);
offset += 4;
proto_tree_add_item(data_tree,hf_aol_wmem_mode, tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(data_tree,hf_aol_horiz_res, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
proto_tree_add_item(data_tree,hf_aol_vert_res, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
proto_tree_add_item(data_tree,hf_aol_num_colors, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2; /* 37b */
/* WAOL 1.5 (48b), >= 2.5 (49b) */
if (tvb_reported_length_remaining(tvb,offset) <= 13) { /* WAOL 1.5 - 3.0 */
if (tvb_reported_length_remaining(tvb,offset) == 13) { /* WAOL > 1.5 */
proto_tree_add_item(data_tree,hf_aol_filler,tvb,offset,1,ENC_BIG_ENDIAN); offset += 1;
}
proto_tree_add_item(data_tree,hf_aol_region, tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
proto_tree_add_item(data_tree,hf_aol_lang, tvb,offset,8,ENC_LITTLE_ENDIAN); offset += 8;
proto_tree_add_item(data_tree,hf_aol_conn_spd,tvb,offset,1,ENC_NA); offset += 1;
} else { /* WAOL >= 4.0 - ??? (52b) */
;
}
return offset;
}
/**
* Get the length of a particular PDU (+6 bytes for the frame)
*/
static guint get_aol_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
int offset, void *data _U_)
{
guint16 plen;
/* Get the PDU length */
plen = tvb_get_ntohs(tvb,offset+3);
return plen + 6;
}
/**
* Dissect a PDU
*/
static int dissect_aol_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
proto_item *ti;
proto_tree *aol_tree;
guint offset = 0;
guint16 pdu_len;
guint8 pdu_type = 0;
/* Set the protocol name, and info column text. */
col_set_str(pinfo->cinfo,COL_PROTOCOL,"AOL");
col_set_str(pinfo->cinfo,COL_INFO,"America Online");
/* Add our tree item, and tree */
ti = proto_tree_add_item(tree,proto_aol,tvb,0,-1,ENC_NA);
aol_tree = proto_item_add_subtree(ti,ett_aol);
pdu_len = tvb_get_ntohs(tvb,3);
/* Add the first few P3 fields */
proto_tree_add_item(aol_tree,hf_aol_start,tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_checksum(aol_tree, tvb, offset, hf_aol_crc, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); offset += 2;
proto_tree_add_item(aol_tree,hf_aol_len, tvb,offset,2,ENC_BIG_ENDIAN); offset += 2;
/* Add sequence fields */
if (pdu_len >= 2) {
proto_tree_add_item(aol_tree,hf_aol_tx_seq,tvb,offset,1,ENC_NA); offset += 1;
proto_tree_add_item(aol_tree,hf_aol_rx_seq,tvb,offset,1,ENC_NA); offset += 1;
pdu_len -= 2;
}
/* Add type (and add it to the tree item / info column) */
if (pdu_len >= 1) {
pdu_type = tvb_get_guint8(tvb,offset) & 0x3f;
col_append_fstr(pinfo->cinfo,COL_INFO," [Type: %s]",val_to_str_const(pdu_type,aol_p3_types,"Unknown"));
proto_item_append_text(ti," [Type: %s]",val_to_str_const(pdu_type,aol_p3_types,"Unknown"));
proto_tree_add_uint(aol_tree,hf_aol_type,tvb,offset,1,pdu_type);
offset += 1; pdu_len -= 1;
}
/* Now for the data... */
if (pdu_len > 0) {
guint old_offset = offset;
if (tvb_reported_length_remaining(tvb,offset) > pdu_len) {
/* Init packets are a special case */
if (pdu_type == AOL_P3_TYPE_INIT) {
offset = dissect_aol_init(tvb,pinfo,offset,aol_tree);
} else {
if (pdu_len >= 2) {
guint16 token;
/* Get the token */
token = tvb_get_ntohs(tvb,offset);
/* Add it */
col_append_fstr(pinfo->cinfo,COL_INFO," [Token: '%c%c']",(token & 0xFF00) >> 8,token & 0xFF);
proto_item_append_text(ti," [Token: '%c%c']",(token & 0xFF00) >> 8,token & 0xFF);
proto_tree_add_uint_format_value(aol_tree,hf_aol_token,tvb,offset,2,token,"'%c%c'",(token & 0xFF00) >> 8,token & 0xFF);
offset += 2; pdu_len -= 2;
}
/* Add the data */
if (pdu_len > 0) {
proto_tree_add_item(aol_tree,hf_aol_data,tvb,offset,pdu_len,ENC_NA);
offset += pdu_len;
}
}
if (offset < (old_offset + pdu_len)) {
/* We didn't parse the entire pdu... */
proto_tree_add_item(aol_tree,hf_aol_udata,tvb,offset,(old_offset+pdu_len)-offset,ENC_NA);
offset = old_offset + pdu_len;
}
} else {
/* Malformed packet */
expert_add_info(pinfo,ti,&ei_aol_pdu_length_bad);
}
}
/* End-of-Frame Marker */
if (tvb_reported_length_remaining(tvb,offset) >= 1) {
proto_tree_add_item(aol_tree,hf_aol_end,tvb,offset,1,ENC_NA);/* offset += 1;*/
} else {
/* Malformed Packet */
expert_add_info(pinfo,ti,&ei_aol_end_missing);
}
return tvb_reported_length(tvb);
}
/**
* Dissect a packet
*/
static int dissect_aol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
/* Ensure this really is an AOL packet */
if (tvb_reported_length(tvb) >= 1 && tvb_get_guint8(tvb,0) != AOL_P3_FRAME_START) return 0;
/* Dissect PDUs */
tcp_dissect_pdus(tvb,pinfo,tree,aol_desegment,9,get_aol_pdu_len,dissect_aol_pdu,data);
return tvb_reported_length(tvb);
}
/**
* Protocol Registration Routine
*
* Registers our protocol.
*/
void proto_register_aol(void) {
/* Header fields */
static hf_register_info hf[] = {
/* Special Stuff */
{ &hf_aol_udata, { "Unparsed Data", "aol.udata", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_init, { "AOL 'INIT' Data", "aol.init_data",FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL }},
/* P3 Frame */
{ &hf_aol_start, { "Start of Frame", "aol.start", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_crc, { "Checksum", "aol.checksum", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_len, { "Length", "aol.len", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_tx_seq, { "Tx Sequence", "aol.tx_seq", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_rx_seq, { "Rx Sequence", "aol.rx_seq", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_type, { "Type", "aol.type", FT_UINT8, BASE_HEX, VALS(aol_p3_types), 0x00, NULL, HFILL }},
{ &hf_aol_token, { "Token", "aol.token", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_data, { "Data", "aol.data", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_end, { "End of Frame", "aol.end", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
/* Init packet */
{ &hf_aol_platform, { "Platform", "aol.init.platform", FT_UINT8, BASE_HEX, VALS(aol_platforms),0x00, NULL, HFILL }},
{ &hf_aol_version, { "Client Version", "aol.init.version", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_subversion, { "Client Subversion","aol.init.subversion", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_unused, { "Unused", "aol.init.unused", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_machine_mem, { "Machine Memory", "aol.init.memory", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_app_mem, { "App Memory", "aol.init.app_memory", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_pc_type, { "PC Type", "aol.init.pc_type", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_rel_month, { "Release Month", "aol.init.rel_month", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_rel_day, { "Release Day", "aol.init.rel_day", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_cust_class, { "Customer Class", "aol.init.cust_class", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_udo_timestamp,{ "UDO Timestamp", "aol.init.udo_ts", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_dos_ver, { "DOS Version", "aol.init.dos_ver", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_sess_flags, { "Session Flags", "aol.init.sess_flags", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_video_type, { "Video Type", "aol.init.video_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_cpu_type, { "CPU Type", "aol.init.cpu_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_media_type, { "Media Type", "aol.init.media_type", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_win_ver, { "Windows Version", "aol.init.win_ver", FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_wmem_mode, { "Windows Mem Type", "aol.init.wmem_mode", FT_UINT8, BASE_DEC, VALS(aol_wmem_mode),0x00, NULL, HFILL }},
{ &hf_aol_horiz_res, { "Horizontal Res", "aol.init.horiz_res", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_vert_res, { "Vertical Res", "aol.init.vert_res", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_num_colors, { "Colors", "aol.init.colors", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_filler, { "Filler Byte", "aol.init.filler", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_region, { "AOL Region", "aol.init.region", FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_lang, { "AOL Language(s)", "aol.init.langs", FT_UINT64, BASE_HEX, NULL, 0x00, NULL, HFILL }},
{ &hf_aol_conn_spd, { "Connection Speed", "aol.init.conn_spd", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
};
/* Trees */
static gint *ett[] = {
&ett_aol,
&ett_aol_data
};
static ei_register_info ei[] = {
{ &ei_aol_pdu_length_bad, { "aol.pdu_length_bad", PI_MALFORMED, PI_ERROR, "pdu length > tvb length", EXPFILL }},
{ &ei_aol_end_missing, { "aol.end_missing", PI_PROTOCOL, PI_WARN, "End of frame marker expected", EXPFILL }},
};
/* Module (for prefs) */
module_t *aol_module;
expert_module_t* expert_aol;
/* Register the protocol and header fields */
proto_aol = proto_register_protocol("America Online","AOL","aol");
proto_register_field_array(proto_aol,hf,array_length(hf));
proto_register_subtree_array(ett,array_length(ett));
expert_aol = expert_register_protocol(proto_aol);
expert_register_field_array(expert_aol, ei, array_length(ei));
/* Register prefs */
aol_module = prefs_register_protocol(proto_aol,NULL);
prefs_register_bool_preference(aol_module,"desegment",
"Reassemble AOL messages spanning multiple TCP segments",
"Whether the AOL dissector should reassemble messages spanning multiple TCP segments. "
"To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" "
"in the TCP protocol settings.",&aol_desegment);
}
/**
* Dissector Handoff Routine
*
* Initialize the dissector.
*/
void proto_reg_handoff_aol(void) {
dissector_handle_t aol_handle;
aol_handle = create_dissector_handle(dissect_aol,proto_aol);
dissector_add_uint_with_preference("tcp.port",AOL_PORT,aol_handle);
}
/* vi:set ts=4: */
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/