Remove all $Id$ from top of file
[metze/wireshark/wip.git] / epan / dissectors / packet-fmtp.c
1 /* packet-fmtp.c
2  *
3  * Routines for FMTP version 2 packet dissection.
4  *
5  * The specifications of this public protocol can be found on Eurocontrol web site:
6  * http://www.eurocontrol.int/ses/public/standard_page/fmtp_spec.html
7  *
8  * Copyright 2011, Christophe Paletou <c.paletou@free.fr>
9  *
10  * Wireshark - Network traffic analyzer
11  * By Gerald Combs <gerald@wireshark.org>
12  * Copyright 1998 Gerald Combs
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  */
28
29 #include "config.h"
30
31 #include <epan/packet.h>
32 #include "packet-tcp.h"
33
34 void proto_register_fmtp(void);
35 void proto_reg_handoff_fmtp(void);
36
37 static int proto_fmtp = -1;
38 static int hf_fmtp_pdu_version = -1;
39 static int hf_fmtp_pdu_reserved = -1;
40 static int hf_fmtp_pdu_type = -1;
41 static int hf_fmtp_pdu_length = -1;
42 static gint ett_fmtp = -1;
43
44 /* #define TCP_PORT_FMTP       8500 */
45 #define FMTP_HEADER_LEN     5
46 #define FMTP_MAX_DATA_LEN   10240
47 #define FMTP_MAX_LEN        FMTP_HEADER_LEN + FMTP_MAX_DATA_LEN
48
49 #define FMTP_TYP_OPERATIONAL    1
50 #define FMTP_TYP_OPERATOR       2
51 #define FMTP_TYP_IDENTIFICATION 3
52 #define FMTP_TYP_SYSTEM         4
53
54 #define INFO_STR_SIZE        1024
55
56 static dissector_handle_t data_handle;
57
58 static const value_string packet_type_names[] = {
59     { FMTP_TYP_OPERATIONAL,    "Operational message" },
60     { FMTP_TYP_OPERATOR,       "Operator message" },
61     { FMTP_TYP_IDENTIFICATION, "Identification message" },
62     { FMTP_TYP_SYSTEM        , "System message" },
63     { 0, NULL }
64 };
65
66 static const value_string system_message_names[] = {
67     { 12337, "Startup" },   /* 0x3031 */
68     { 12336, "Shutdown" },  /* 0x3030 */
69     { 12339, "Heartbeat" }, /* 0x3033 */
70     { 0, NULL }
71 };
72
73 static int
74 dissect_fmtp_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
75 {
76     guint8      packet_type;
77     guint16     packet_len;
78     tvbuff_t   *next_tvb;
79     proto_item *ti = NULL;
80     proto_tree *fmtp_tree = NULL;
81
82     packet_type = tvb_get_guint8(tvb, 4);
83     packet_len  = tvb_get_ntohs(tvb, 2);
84
85     col_set_str(pinfo->cinfo, COL_PROTOCOL, "FMTP");
86
87     /* Clear out stuff in the info column */
88     col_clear(pinfo->cinfo, COL_INFO);
89
90     ti = proto_tree_add_item(tree, proto_fmtp, tvb, 0, -1, ENC_NA);
91     proto_item_append_text(ti, ", %s",
92         val_to_str(packet_type, packet_type_names, "Unknown (0x%02x)"));
93
94     switch (packet_type) {
95
96         case FMTP_TYP_IDENTIFICATION:
97             proto_item_append_text(ti, " (%s)",
98                 tvb_get_string(wmem_packet_scope(), tvb, FMTP_HEADER_LEN, packet_len-FMTP_HEADER_LEN));
99             col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
100                 val_to_str(packet_type, packet_type_names, "Unknown (0x%02x)"),
101                 tvb_get_string(wmem_packet_scope(), tvb, FMTP_HEADER_LEN, packet_len-FMTP_HEADER_LEN));
102             break;
103
104         case FMTP_TYP_SYSTEM:
105             proto_item_append_text(ti, " (%s)",
106                 tvb_get_string(wmem_packet_scope(), tvb, FMTP_HEADER_LEN, packet_len-FMTP_HEADER_LEN));
107             col_add_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
108                 val_to_str(packet_type, packet_type_names, "Unknown (0x%02x)"),
109                 val_to_str(tvb_get_ntohs(tvb, FMTP_HEADER_LEN), system_message_names, "Unknown (0x%02x)"));
110             break;
111
112         default:
113             col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
114                 val_to_str(packet_type, packet_type_names, "Unknown (0x%02x)"));
115             break;
116     }
117     if (tree) { /* we are being asked for details */
118         fmtp_tree = proto_item_add_subtree(ti, ett_fmtp);
119         proto_tree_add_item(fmtp_tree, hf_fmtp_pdu_version,  tvb, 0, 1, ENC_NA);
120         proto_tree_add_item(fmtp_tree, hf_fmtp_pdu_reserved, tvb, 1, 1, ENC_NA);
121         proto_tree_add_item(fmtp_tree, hf_fmtp_pdu_length,   tvb, 2, 2, ENC_BIG_ENDIAN);
122         proto_tree_add_item(fmtp_tree, hf_fmtp_pdu_type,     tvb, 4, 1, ENC_NA);
123
124         next_tvb = tvb_new_subset_remaining(tvb, FMTP_HEADER_LEN);
125         call_dissector(data_handle, next_tvb, pinfo, fmtp_tree);
126     }
127
128     return tvb_length(tvb);
129 }
130
131 static guint
132 get_fmtp_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
133 {
134     return (guint)tvb_get_ntohs(tvb, offset+2);
135 }
136
137 static gboolean
138 dissect_fmtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
139 {
140     /*
141      * Check that packet looks like FMTP before going further
142      */
143     /* VERSION must currently be 0x02 */
144     if (tvb_get_guint8(tvb, 0) != 0x02) return (FALSE);
145     /* RESERVED must currently be 0x00 */
146     if (tvb_get_guint8(tvb, 1) != 0x00) return (FALSE);
147     /* LENGTH must currently not exceed 5 (header) + 10240 (data) */
148     if (tvb_get_ntohs(tvb, 2) > FMTP_MAX_LEN) return (FALSE);
149     /* TYP must currently be in range 0x01-0x04 */
150     if ((tvb_get_guint8(tvb, 4) < 0x01) || (tvb_get_guint8(tvb, 4) > 0x04))
151         return (FALSE);
152
153     tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FMTP_HEADER_LEN,
154                      get_fmtp_message_len, dissect_fmtp_message, data);
155     return (TRUE);
156 }
157
158 void
159 proto_register_fmtp(void)
160 {
161     static hf_register_info hf[] = {
162         { &hf_fmtp_pdu_version,
163             { "Version", "fmtp.version",
164             FT_UINT8, BASE_DEC,
165             NULL, 0x0,
166             NULL, HFILL }
167         },
168         { &hf_fmtp_pdu_reserved,
169             { "Reserved", "fmtp.reserved",
170             FT_UINT8, BASE_DEC,
171             NULL, 0x0,
172             NULL, HFILL }
173         },
174         { &hf_fmtp_pdu_length,
175             { "Length", "fmtp.length",
176             FT_UINT16, BASE_DEC,
177             NULL, 0x0,
178             NULL, HFILL }
179         },
180         { &hf_fmtp_pdu_type,
181             { "Type", "fmtp.type",
182             FT_UINT8, BASE_DEC,
183             VALS(packet_type_names), 0x0,
184             NULL, HFILL }
185         }
186     };
187
188     /* Setup protocol subtree array */
189     static gint *ett[] = {
190         &ett_fmtp
191     };
192
193     proto_fmtp = proto_register_protocol(
194         "Flight Message Transfer Protocol (FMTP)",
195         "FMTP",
196         "fmtp");
197
198     proto_register_field_array(proto_fmtp, hf, array_length(hf));
199     proto_register_subtree_array(ett, array_length(ett));
200 }
201
202 void
203 proto_reg_handoff_fmtp(void)
204 {
205     /* Register as heuristic dissector for TCP */
206     heur_dissector_add("tcp", dissect_fmtp, proto_fmtp);
207     data_handle = find_dissector("data");
208 }
209
210 /*
211  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
212  *
213  * Local variables:
214  * c-basic-offset: 4
215  * tab-width: 8
216  * indent-tabs-mode: nil
217  * End:
218  *
219  * vi: set shiftwidth=4 tabstop=8 expandtab:
220  * :indentSize=4:tabSize=8:noTabs=true:
221  */
222