Use MAC address documentation range in filter examples
[metze/wireshark/wip.git] / epan / dissectors / packet-sita.c
1 /* packet-sita.c
2  * Routines for SITA protocol dissection (ALC, UTS, Frame Relay, X.25)
3  * with a SITA specific link layer information header
4  *
5  * Copyright 2007, Fulko Hew, SITA INC Canada, Inc.
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24  */
25
26 /* Use indentation = 4 */
27
28 #include "config.h"
29
30
31 #include <epan/packet.h>
32 #include <wiretap/wtap.h>
33 void proto_register_sita(void);
34 void proto_reg_handoff_sita(void);
35
36 static dissector_table_t    sita_dissector_table;
37 static dissector_handle_t   data_handle;
38 static gint                 ett_sita            = -1;
39 static gint                 ett_sita_flags      = -1;
40 static gint                 ett_sita_signals    = -1;
41 static gint                 ett_sita_errors1    = -1;
42 static gint                 ett_sita_errors2    = -1;
43 static int                  proto_sita          = -1;       /* Initialize the protocol and registered fields */
44 static int                  hf_dir              = -1;
45 static int                  hf_framing          = -1;
46 static int                  hf_parity           = -1;
47 static int                  hf_collision        = -1;
48 static int                  hf_longframe        = -1;
49 static int                  hf_shortframe       = -1;
50 static int                  hf_droppedframe     = -1;
51 static int                  hf_nonaligned       = -1;
52 static int                  hf_abort            = -1;
53 static int                  hf_lostcd           = -1;
54 static int                  hf_lostcts          = -1;
55 static int                  hf_rxdpll           = -1;
56 static int                  hf_overrun          = -1;
57 static int                  hf_length           = -1;
58 static int                  hf_crc              = -1;
59 static int                  hf_break            = -1;
60 static int                  hf_underrun         = -1;
61 static int                  hf_uarterror        = -1;
62 static int                  hf_rtxlimit         = -1;
63 static int                  hf_proto            = -1;
64 static int                  hf_dsr              = -1;
65 static int                  hf_dtr              = -1;
66 static int                  hf_cts              = -1;
67 static int                  hf_rts              = -1;
68 static int                  hf_dcd              = -1;
69 static int                  hf_signals          = -1;
70
71 #define MAX_FLAGS_LEN 64                                    /* max size of a 'flags' decoded string */
72 #define IOP                 "Local"
73 #define REMOTE              "Remote"
74
75 static const gchar *
76 format_flags_string(guchar value, const gchar *array[])
77 {
78     int         i;
79     guint       bpos;
80     wmem_strbuf_t   *buf;
81     const char  *sep = "";
82
83     buf = wmem_strbuf_sized_new(wmem_packet_scope(), MAX_FLAGS_LEN, MAX_FLAGS_LEN);
84     for (i = 0; i < 8; i++) {
85         bpos = 1 << i;
86         if (value & bpos) {
87             if (array[i][0]) {
88                 /* there is a string to emit... */
89                 wmem_strbuf_append_printf(buf, "%s%s", sep,
90                     array[i]);
91                 sep = ", ";
92             }
93         }
94     }
95     return wmem_strbuf_get_str(buf);
96 }
97
98 static void
99 dissect_sita(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
100 {
101     proto_item  *ti;
102     guchar      flags, signals, errors1, errors2, proto;
103     const gchar *errors1_string, *errors2_string, *flags_string;
104     proto_tree  *sita_tree          = NULL;
105     proto_tree  *sita_flags_tree    = NULL;
106     proto_tree  *sita_errors1_tree  = NULL;
107     proto_tree  *sita_errors2_tree  = NULL;
108     static const gchar *rx_errors1_str[]   = {"Framing",       "Parity",   "Collision",    "Long-frame",   "Short-frame",  "",         "",     ""              };
109     static const gchar *rx_errors2_str[]   = {"Non-Aligned",   "Abort",    "CD-lost",      "DPLL",         "Overrun",      "Length",   "CRC",  "Break"         };
110 #if 0
111     static const gchar   *tx_errors1_str[]   = {"",              "",         "",             "",             "",             "",         "",     ""              };
112 #endif
113     static const gchar *tx_errors2_str[]   = {"Underrun",      "CTS-lost", "UART",         "ReTx-limit",   "",             "",         "",     ""              };
114     static const gchar *flags_str[]        = {"",              "",         "",             "",             "",             "",         "",     "No-buffers"    };
115
116
117     static const int * signal_flags[] = {
118         &hf_dcd,
119         &hf_rts,
120         &hf_cts,
121         &hf_dtr,
122         &hf_dsr,
123         NULL
124     };
125
126     col_clear(pinfo->cinfo, COL_PROTOCOL);      /* erase the protocol */
127     col_clear(pinfo->cinfo, COL_INFO);          /* and info columns so that the next decoder can fill them in */
128
129     flags   = pinfo->pseudo_header->sita.sita_flags;
130     signals = pinfo->pseudo_header->sita.sita_signals;
131     errors1 = pinfo->pseudo_header->sita.sita_errors1;
132     errors2 = pinfo->pseudo_header->sita.sita_errors2;
133     proto   = pinfo->pseudo_header->sita.sita_proto;
134
135     if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
136         col_set_str(pinfo->cinfo, COL_DEF_SRC, IOP);  /* set the source (direction) column accordingly */
137     } else {
138         col_set_str(pinfo->cinfo, COL_DEF_SRC, REMOTE);
139     }
140
141     col_set_str(pinfo->cinfo, COL_INFO, "");
142
143     if (tree) {
144         ti = proto_tree_add_protocol_format(tree, proto_sita, tvb, 0, 0, "Link Layer");
145         sita_tree = proto_item_add_subtree(ti, ett_sita);
146
147         proto_tree_add_uint(sita_tree, hf_proto, tvb, 0, 0, proto);
148
149         flags_string = format_flags_string(flags, flags_str);
150         sita_flags_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
151                 ett_sita_flags, NULL, "Flags: 0x%02x (From %s)%s%s",
152                 flags,
153                 ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) ? IOP : REMOTE,
154                 strlen(flags_string) ? ", " : "",
155                 flags_string);
156         proto_tree_add_boolean(sita_flags_tree, hf_droppedframe,    tvb, 0, 0, flags);
157         proto_tree_add_boolean(sita_flags_tree, hf_dir,             tvb, 0, 0, flags);
158
159         proto_tree_add_bitmask_value_with_flags(sita_tree, tvb, 0, hf_signals, ett_sita_signals,
160                                                 signal_flags, signals, BMT_NO_FALSE|BMT_NO_TFS);
161
162         if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_RXED) {
163             errors1_string = format_flags_string(errors1, rx_errors1_str);
164             sita_errors1_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
165                 ett_sita_errors1, NULL, "Receive Status: 0x%02x %s", errors1, errors1_string);
166             proto_tree_add_boolean(sita_errors1_tree, hf_shortframe,    tvb, 0, 0, errors1);
167             proto_tree_add_boolean(sita_errors1_tree, hf_longframe,     tvb, 0, 0, errors1);
168             proto_tree_add_boolean(sita_errors1_tree, hf_collision,     tvb, 0, 0, errors1);
169             proto_tree_add_boolean(sita_errors1_tree, hf_parity,        tvb, 0, 0, errors1);
170             proto_tree_add_boolean(sita_errors1_tree, hf_framing,       tvb, 0, 0, errors1);
171
172             errors2_string = format_flags_string(errors2, rx_errors2_str);
173             sita_errors2_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
174                 ett_sita_errors2, NULL, "Receive Status: 0x%02x %s", errors2, errors2_string);
175             proto_tree_add_boolean(sita_errors2_tree, hf_break,         tvb, 0, 0, errors2);
176             proto_tree_add_boolean(sita_errors2_tree, hf_crc,           tvb, 0, 0, errors2);
177             proto_tree_add_boolean(sita_errors2_tree, hf_length,        tvb, 0, 0, errors2);
178             proto_tree_add_boolean(sita_errors2_tree, hf_overrun,       tvb, 0, 0, errors2);
179             proto_tree_add_boolean(sita_errors2_tree, hf_rxdpll,        tvb, 0, 0, errors2);
180             proto_tree_add_boolean(sita_errors2_tree, hf_lostcd,        tvb, 0, 0, errors2);
181             proto_tree_add_boolean(sita_errors2_tree, hf_abort,         tvb, 0, 0, errors2);
182             proto_tree_add_boolean(sita_errors2_tree, hf_nonaligned,    tvb, 0, 0, errors2);
183         } else {
184             errors2_string = format_flags_string(errors2, tx_errors2_str);
185             sita_errors1_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
186                 ett_sita_errors1, NULL, "Transmit Status: 0x%02x %s", errors2, errors2_string);
187             proto_tree_add_boolean(sita_errors1_tree, hf_rtxlimit,      tvb, 0, 0, errors2);
188             proto_tree_add_boolean(sita_errors1_tree, hf_uarterror,     tvb, 0, 0, errors2);
189             proto_tree_add_boolean(sita_errors1_tree, hf_lostcts,       tvb, 0, 0, errors2);
190             proto_tree_add_boolean(sita_errors1_tree, hf_underrun,      tvb, 0, 0, errors2);
191         }
192     }
193
194     /* try to find and run an applicable dissector */
195     if (!dissector_try_uint(sita_dissector_table, pinfo->pseudo_header->sita.sita_proto, tvb, pinfo, tree)) {
196         /* if one can't be found... tell them we don't know how to decode this protocol
197            and give them the details then */
198         col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
199         col_add_fstr(pinfo->cinfo, COL_INFO, "IOP protocol number: %u", pinfo->pseudo_header->sita.sita_proto);
200         call_dissector(data_handle, tvb, pinfo, tree);          /* call the generic (hex display) decoder instead */
201     }
202 }
203
204 static const true_false_string tfs_sita_flags       = { "From Remote",  "From Local"    };
205 static const true_false_string tfs_sita_error       = { "Error",        ""              };
206 static const true_false_string tfs_sita_violation   = { "Violation",    ""              };
207 static const true_false_string tfs_sita_received    = { "Received",     ""              };
208 static const true_false_string tfs_sita_lost        = { "Lost",         ""              };
209 static const true_false_string tfs_sita_exceeded    = { "Exceeded",     ""              };
210 static const true_false_string tfs_sita_on_off      = { "On",           "Off"           };
211
212 static const value_string tfs_sita_proto[] = {
213     { SITA_PROTO_UNUSED,        "Unused"                },
214     { SITA_PROTO_BOP_LAPB,      "LAPB"                  },
215     { SITA_PROTO_ETHERNET,      "Ethernet"              },
216     { SITA_PROTO_ASYNC_INTIO,   "Async (Interrupt I/O)" },
217     { SITA_PROTO_ASYNC_BLKIO,   "Async (Block I/O)"     },
218     { SITA_PROTO_ALC,           "IPARS"                 },
219     { SITA_PROTO_UTS,           "UTS"                   },
220     { SITA_PROTO_PPP_HDLC,      "PPP/HDLC"              },
221     { SITA_PROTO_SDLC,          "SDLC"                  },
222     { SITA_PROTO_TOKENRING,     "Token Ring"            },
223     { SITA_PROTO_I2C,           "I2C"                   },
224     { SITA_PROTO_DPM_LINK,      "DPM Link"              },
225     { SITA_PROTO_BOP_FRL,       "Frame Relay"           },
226     { 0,                        NULL                    }
227 };
228
229 void
230 proto_register_sita(void)
231 {
232     static hf_register_info hf[] = {
233         { &hf_proto,
234           { "Protocol", "sita.errors.protocol",
235             FT_UINT8, BASE_HEX, VALS(tfs_sita_proto), 0,
236             "Protocol value", HFILL }
237         },
238
239         { &hf_dir,
240           { "Direction", "sita.flags.flags",
241             FT_BOOLEAN, 8, TFS(&tfs_sita_flags), SITA_FRAME_DIR,
242             "TRUE 'from Remote', FALSE 'from Local'",   HFILL }
243         },
244         { &hf_droppedframe,
245           { "No Buffers", "sita.flags.droppedframe",
246             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_NO_BUFFER,
247             "TRUE if Buffer Failure", HFILL }
248         },
249
250         { &hf_framing,
251           { "Framing", "sita.errors.framing",
252             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_FRAMING,
253             "TRUE if Framing Error", HFILL }
254         },
255         { &hf_parity,
256           { "Parity", "sita.errors.parity",
257             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_PARITY,
258             "TRUE if Parity Error", HFILL }
259         },
260         { &hf_collision,
261           { "Collision", "sita.errors.collision",
262             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_COLLISION,
263             "TRUE if Collision", HFILL }
264         },
265         { &hf_longframe,
266           { "Long Frame", "sita.errors.longframe",
267             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_FRAME_LONG,
268             "TRUE if Long Frame Received", HFILL }
269         },
270         { &hf_shortframe,
271           { "Short Frame", "sita.errors.shortframe",
272             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_FRAME_SHORT,
273             "TRUE if Short Frame", HFILL }
274         },
275         { &hf_nonaligned,
276           { "NonAligned", "sita.errors.nonaligned",
277             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_NONOCTET_ALIGNED,
278             "TRUE if NonAligned Frame", HFILL }
279         },
280         { &hf_abort,
281           { "Abort", "sita.errors.abort",
282             FT_BOOLEAN, 8, TFS(&tfs_sita_received), SITA_ERROR_RX_ABORT,
283             "TRUE if Abort Received", HFILL }
284         },
285         { &hf_lostcd,
286           { "Carrier", "sita.errors.lostcd",
287             FT_BOOLEAN, 8, TFS(&tfs_sita_lost), SITA_ERROR_RX_CD_LOST,
288             "TRUE if Carrier Lost", HFILL }
289         },
290         { &hf_rxdpll,
291           { "DPLL", "sita.errors.rxdpll",
292             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_DPLL,
293             "TRUE if DPLL Error", HFILL }
294         },
295         { &hf_overrun,
296           { "Overrun", "sita.errors.overrun",
297             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_OVERRUN,
298             "TRUE if Overrun Error", HFILL }
299         },
300         { &hf_length,
301           { "Length", "sita.errors.length",
302             FT_BOOLEAN, 8, TFS(&tfs_sita_violation), SITA_ERROR_RX_FRAME_LEN_VIOL,
303             "TRUE if Length Violation", HFILL }
304         },
305         { &hf_crc,
306           { "CRC", "sita.errors.crc",
307             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_RX_CRC,
308             "TRUE if CRC Error", HFILL }
309         },
310         { &hf_break,
311           { "Break", "sita.errors.break",
312             FT_BOOLEAN, 8, TFS(&tfs_sita_received), SITA_ERROR_RX_BREAK,
313             "TRUE if Break Received", HFILL }
314         },
315
316         { &hf_underrun,
317           { "Underrun", "sita.errors.underrun",
318             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_TX_UNDERRUN,
319             "TRUE if Tx Underrun", HFILL }
320         },
321         { &hf_lostcts,
322           { "Clear To Send", "sita.errors.lostcts",
323             FT_BOOLEAN, 8, TFS(&tfs_sita_lost), SITA_ERROR_TX_CTS_LOST,
324             "TRUE if Clear To Send Lost", HFILL }
325         },
326         { &hf_uarterror,
327           { "UART", "sita.errors.uarterror",
328             FT_BOOLEAN, 8, TFS(&tfs_sita_error), SITA_ERROR_TX_UART_ERROR,
329             "TRUE if UART Error", HFILL }
330         },
331         { &hf_rtxlimit,
332           { "Retx Limit", "sita.errors.rtxlimit",
333             FT_BOOLEAN, 8, TFS(&tfs_sita_exceeded), SITA_ERROR_TX_RETX_LIMIT,
334             "TRUE if Retransmit Limit reached", HFILL }
335         },
336
337         { &hf_dsr,
338           { "DSR", "sita.signals.dsr",
339             FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_DSR,
340             "TRUE if Data Set Ready", HFILL }
341         },
342         { &hf_dtr,
343           { "DTR", "sita.signals.dtr",
344             FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_DTR,
345             "TRUE if Data Terminal Ready", HFILL }
346         },
347         { &hf_cts,
348           { "CTS", "sita.signals.cts",
349             FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_CTS,
350             "TRUE if Clear To Send", HFILL }
351         },
352         { &hf_rts,
353           { "RTS", "sita.signals.rts",
354             FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_RTS,
355             "TRUE if Request To Send", HFILL }
356         },
357         { &hf_dcd,
358           { "DCD", "sita.signals.dcd",
359             FT_BOOLEAN, 8, TFS(&tfs_sita_on_off), SITA_SIG_DCD,
360             "TRUE if Data Carrier Detect", HFILL }
361         },
362         { &hf_signals,
363           { "Signals", "sita.signals",
364             FT_UINT8, BASE_HEX, NULL, 0,
365             NULL, HFILL }
366         },
367     };
368
369     static gint *ett[] = {
370         &ett_sita,
371         &ett_sita_flags,
372         &ett_sita_signals,
373         &ett_sita_errors1,
374         &ett_sita_errors2,
375     };
376
377     proto_sita = proto_register_protocol("Societe Internationale de Telecommunications Aeronautiques", "SITA", "sita"); /* name, short name,abbreviation */
378     sita_dissector_table = register_dissector_table("sita.proto", "SITA protocol number", FT_UINT8, BASE_HEX);
379     proto_register_field_array(proto_sita, hf, array_length(hf));
380     proto_register_subtree_array(ett, array_length(ett));
381     register_dissector("sita", dissect_sita, proto_sita);
382 }
383
384 void
385 proto_reg_handoff_sita(void)
386 {
387     dissector_handle_t  lapb_handle;
388     dissector_handle_t  frame_relay_handle;
389     dissector_handle_t  uts_handle;
390     dissector_handle_t  ipars_handle;
391     dissector_handle_t  sita_handle;
392
393     lapb_handle     = find_dissector("lapb");
394     frame_relay_handle  = find_dissector("fr");
395     uts_handle      = find_dissector("uts");
396     ipars_handle        = find_dissector("ipars");
397     sita_handle         = find_dissector("sita");
398     data_handle     = find_dissector("data");
399
400     dissector_add_uint("sita.proto", SITA_PROTO_BOP_LAPB,   lapb_handle);
401     dissector_add_uint("sita.proto", SITA_PROTO_BOP_FRL,        frame_relay_handle);
402     dissector_add_uint("sita.proto", SITA_PROTO_UTS,        uts_handle);
403     dissector_add_uint("sita.proto", SITA_PROTO_ALC,        ipars_handle);
404     dissector_add_uint("wtap_encap", WTAP_ENCAP_SITA,       sita_handle);
405 }
406
407 /*
408  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
409  *
410  * Local variables:
411  * c-basic-offset: 4
412  * tab-width: 8
413  * indent-tabs-mode: nil
414  * End:
415  *
416  * vi: set shiftwidth=4 tabstop=8 expandtab:
417  * :indentSize=4:tabSize=8:noTabs=true:
418  */