2 * Reliable Multicast Transport (RMT)
3 * NORM Protocol Instantiation dissector
4 * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net>
6 * Negative-acknowledgment (NACK)-Oriented Reliable Multicast (NORM):
7 * ------------------------------------------------------------------
9 * This protocol is designed to provide end-to-end reliable transport of
10 * bulk data objects or streams over generic IP multicast routing and
11 * forwarding services. NORM uses a selective, negative acknowledgment
12 * mechanism for transport reliability and offers additional protocol
13 * mechanisms to allow for operation with minimal "a priori"
14 * coordination among senders and receivers.
17 * RFC 3490, Negative-acknowledgment (NACK)-Oriented Reliable Multicast (NORM) Protocol
21 * Ethereal - Network traffic analyzer
22 * By Gerald Combs <gerald@ethereal.com>
23 * Copyright 1998 Gerald Combs
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
50 #include <epan/packet.h>
51 #include <epan/prefs.h>
53 #include "packet-rmt-norm.h"
56 const value_string string_norm_type[] =
67 /* Initialize the protocol and registered fields */
68 /* ============================================= */
70 static int proto = -1;
72 static struct _norm_hf hf;
73 static struct _norm_ett ett;
75 static gboolean preferences_initialized = FALSE;
76 static struct _norm_prefs preferences;
77 static struct _norm_prefs preferences_old;
82 /* Set/Reset preferences to default values */
83 static void norm_prefs_set_default(struct _norm_prefs *prefs)
85 fec_prefs_set_default(&prefs->fec);
88 /* Register preferences */
89 static void norm_prefs_register(struct _norm_prefs *prefs, module_t *module)
91 fec_prefs_register(&prefs->fec, module);
94 /* Save preferences to alc_prefs_old */
95 static void norm_prefs_save(struct _norm_prefs *p, struct _norm_prefs *p_old)
100 /* Code to actually dissect the packets */
101 /* ==================================== */
103 static void dissect_norm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
105 /* Logical packet representation */
108 /* Offset for subpacket dissection */
111 /* Set up structures needed to add the protocol subtree and manage it */
113 proto_tree *norm_tree;
115 /* Structures and variables initialization */
117 memset(&norm, 0, sizeof(struct _norm));
119 /* Update packet info */
120 pinfo->current_proto = "NORM";
122 /* Make entries in Protocol column and Info column on summary display */
123 if (check_col(pinfo->cinfo, COL_PROTOCOL))
124 col_set_str(pinfo->cinfo, COL_PROTOCOL, "NORM");
125 if (check_col(pinfo->cinfo, COL_INFO))
126 col_clear(pinfo->cinfo, COL_INFO);
128 /* NORM header dissection, part 1 */
129 /* ------------------------------ */
131 norm.version = hi_nibble(tvb_get_guint8(tvb, offset));
135 /* Create subtree for the NORM protocol */
136 ti = proto_tree_add_item(tree, proto, tvb, offset, -1, FALSE);
137 norm_tree = proto_item_add_subtree(ti, ett.main);
139 /* Fill the NORM subtree */
140 proto_tree_add_uint(norm_tree, hf.version, tvb, offset, 1, norm.version);
145 /* This dissector supports only NORMv1 packets.
146 * If norm.version > 1 print only version field and quit.
148 if (norm.version == 1) {
150 /* NORM header dissection, part 2 */
151 /* ------------------------------ */
153 norm.type = lo_nibble(tvb_get_guint8(tvb, offset));
154 norm.hlen = tvb_get_guint8(tvb, offset+1);
155 norm.sequence = tvb_get_ntohs(tvb, offset+2);
156 norm.source_id = tvb_get_ntohl(tvb, offset+4);
160 proto_tree_add_uint(norm_tree, hf.type, tvb, offset, 1, norm.type);
161 proto_tree_add_uint(norm_tree, hf.hlen, tvb, offset+1, 1, norm.hlen);
162 proto_tree_add_uint(norm_tree, hf.sequence, tvb, offset+2, 2, norm.sequence);
163 proto_tree_add_uint(norm_tree, hf.source_id, tvb, offset+4, 4, norm.source_id);
168 /* Add the Payload item */
169 if (tvb_length(tvb) > offset)
170 proto_tree_add_none_format(norm_tree, hf.payload, tvb, offset, -1, "Payload (%u bytes)", tvb_length(tvb) - offset);
172 /* Complete entry in Info column on summary display */
173 /* ------------------------------------------------ */
175 if (check_col(pinfo->cinfo, COL_INFO))
179 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "INFO");
183 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "DATA");
187 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "CMD");
191 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "NACK");
195 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "ACK");
199 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "REPORT");
203 col_append_sep_str(pinfo->cinfo, COL_INFO, " ", "Unknown type");
210 proto_tree_add_text(norm_tree, tvb, 0, -1, "Sorry, this dissector supports NORM version 1 only");
212 /* Complete entry in Info column on summary display */
213 if (check_col(pinfo->cinfo, COL_INFO))
214 col_add_fstr(pinfo->cinfo, COL_INFO, "Version: %u (not supported)", norm.version);
218 void proto_reg_handoff_norm(void)
220 static dissector_handle_t handle;
222 if (!preferences_initialized)
224 preferences_initialized = TRUE;
225 handle = create_dissector_handle(dissect_norm, proto);
226 dissector_add_handle("udp.port", handle);
229 norm_prefs_save(&preferences, &preferences_old);
232 void proto_register_norm(void)
234 /* Setup NORM header fields */
235 static hf_register_info hf_ptr[] = {
238 { "Version", "norm.version", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
240 { "Message Type", "norm.type", FT_UINT8, BASE_DEC, VALS(string_norm_type), 0x0, "", HFILL }},
242 { "Header length", "norm.hlen", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
244 { "Sequence", "norm.sequence", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
246 { "Source ID", "norm.source_id", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
248 FEC_FIELD_ARRAY(hf.fec, "alc"),
251 { "Payload", "norm.payload", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }}
254 /* Setup protocol subtree array */
255 static gint *ett_ptr[] = {
258 FEC_SUBTREE_ARRAY(ett.fec)
263 /* Clear hf and ett fields */
264 memset(&hf, 0xff, sizeof(struct _norm_hf));
265 memset(&ett, 0xff, sizeof(struct _norm_ett));
267 /* Register the protocol name and description */
268 proto = proto_register_protocol("Negative-acknowledgment Oriented Reliable Multicast", "NORM", "norm");
270 /* Register the header fields and subtrees used */
271 proto_register_field_array(proto, hf_ptr, array_length(hf_ptr));
272 proto_register_subtree_array(ett_ptr, array_length(ett_ptr));
274 /* Reset preferences */
275 norm_prefs_set_default(&preferences);
276 norm_prefs_save(&preferences, &preferences_old);
278 /* Register preferences */
279 module = prefs_register_protocol(proto, proto_reg_handoff_norm);
280 norm_prefs_register(&preferences, module);