Fix for bug 5422:
[obnox/wireshark/wip.git] / epan / dissectors / packet-rmt-fec.c
1 /* packet-rmt-fec.c
2  * Reliable Multicast Transport (RMT)
3  * FEC Building Block dissector
4  * Copyright 2005, Stefano Pettini <spettini@users.sourceforge.net>
5  *
6  * Forward Error Correction (ALC):
7  * -------------------------------
8  *
9  * The goal of the FEC building block is to describe functionality
10  * directly related to FEC codes that is common to all reliable content
11  * delivery IP multicast protocols, and to leave out any additional
12  * functionality that is specific to particular protocols.
13  *
14  * References:
15  *     RFC 3452, Forward Error Correction Building Block
16  *     RFC 3695, Compact Forward Error Correction (FEC) Schemes
17  *     Simple XOR, Reed-Solomon, and Parity Check Matrix-based FEC Schemes draft-peltotalo-rmt-bb-fec-supp-xor-pcm-rs-00
18  *     IANA RMT FEC parameters (http://www.iana.org/assignments/rmt-fec-parameters)
19  *
20  * $Id$
21  *
22  * Wireshark - Network traffic analyzer
23  * By Gerald Combs <gerald@wireshark.org>
24  * Copyright 1998 Gerald Combs
25  *
26  * This program is free software; you can redistribute it and/or
27  * modify it under the terms of the GNU General Public License
28  * as published by the Free Software Foundation; either version 2
29  * of the License, or (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34  * GNU General Public License for more details.
35  *
36  * You should have received a copy of the GNU General Public License
37  * along with this program; if not, write to the Free Software
38  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
39  */
40
41 #ifdef HAVE_CONFIG_H
42 # include "config.h"
43 #endif
44
45 #include <stdlib.h>
46
47 #include <glib.h>
48
49 #include <epan/packet.h>
50 #include <epan/prefs.h>
51
52 #include "packet-rmt-fec.h"
53
54 /* String tables */
55 const value_string string_fec_encoding_id[] =
56 {
57         { 0, "Compact No-Code" },
58         { 2, "Simple XOR, Reed-Solomon, and Parity Check Matrix-based FEC Codes" },
59         { 128, "Small Block, Large Block and Expandable FEC Codes" },
60         { 129, "Small Block Systematic FEC Codes" },
61         { 130, "Compact FEC Codes" },
62         { 132, "Simple XOR, Reed-Solomon, and Parity Check Matrix-based FEC Codes" },
63         { 0, NULL }
64 };
65
66 /* FEC exported functions */
67 /* ====================== */
68
69 /* Info */
70 /* ---- */
71
72 void fec_info_column(struct _fec *fec, packet_info *pinfo)
73 {
74         if (fec->sbn_present)
75                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "SBN: %u", fec->sbn);
76
77         if (fec->esi_present)
78                 col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "ESI: 0x%X", fec->esi);
79 }
80
81 /* Dissection */
82 /* ---------- */
83
84 /* Decode an EXT_FTI extension and fill FEC array */
85 void fec_decode_ext_fti(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett, struct _fec_ptr f)
86 {
87         proto_item* ti = NULL;
88         proto_tree *ext_tree;
89
90         if (tree)
91                 ti = proto_tree_add_none_format(tree, f.hf->fti_header, tvb, e->offset, e->length,
92                         "EXT_FTI, FEC Object Transmission Information (%u)", e->het);
93
94         if (f.fec->encoding_id_present)
95         {
96                 ext_tree = proto_item_add_subtree(ti, ett);
97                 rmt_ext_decode_default_header(e, tvb, ext_tree);
98
99                 /* Decode 48-bit length field */
100                 f.fec->transfer_length = tvb_get_ntoh64(tvb, e->offset) & G_GINT64_CONSTANT(0xFFFFFFFFFFFFU);
101
102                 if (f.fec->encoding_id >= 128)
103                 {
104                         /* Decode FEC Instance ID */
105                         f.fec->instance_id_present = TRUE;
106                         f.fec->instance_id = (guint8) tvb_get_ntohs(tvb, e->offset+8);
107                 }
108
109                 if (tree)
110                         proto_tree_add_uint64(ext_tree, f.hf->fti_transfer_length, tvb, e->offset+2, 6, f.fec->transfer_length);
111
112                 switch (f.fec->encoding_id)
113                 {
114                 case 0:
115                 case 2:
116                 case 128:
117                 case 130:
118                         f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10);
119                         f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12);
120
121                         if (tree)
122                         {
123                                 proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length);
124                                 proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length);
125                         }
126                         break;
127
128                 case 129:
129                         f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10);
130                         f.fec->max_source_block_length = tvb_get_ntohs(tvb, e->offset+12);
131                         f.fec->max_number_encoding_symbols = tvb_get_ntohs(tvb, e->offset+14);
132
133                         if (tree)
134                         {
135                                 proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length);
136                                 proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 2, f.fec->max_source_block_length);
137                                 proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+14, 2, f.fec->max_number_encoding_symbols);
138                         }
139                         break;
140
141                 case 132:
142                         f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10);
143                         f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12);
144                         f.fec->max_number_encoding_symbols = tvb_get_ntohl(tvb, e->offset+16);
145
146                         if (tree)
147                         {
148                                 proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length);
149                                 proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length);
150                                 proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+16, 4, f.fec->max_number_encoding_symbols);
151                         }
152                         break;
153                 }
154
155         } else
156                 if (tree)
157                         rmt_ext_decode_default_subtree(e, tvb, ti, ett);
158 }
159
160 /* Dissect a FEC header:
161  * fec - ptr to the logical FEC packet representation to fill
162  * hf - ptr to header fields array
163  * ett - ptr to ett array
164  * prefs - ptr to FEC prefs array
165  * tvb - buffer
166  * pinfo - packet info
167  * tree - tree where to add FEC header subtree
168  * offset - ptr to offset to use and update
169  */
170 void fec_dissector(struct _fec_ptr f, tvbuff_t *tvb, proto_tree *tree, guint *offset)
171 {
172         proto_item *ti;
173         proto_tree *fec_tree;
174         guint offset_save = *offset;
175
176         /* Create the FEC subtree */
177         if (tree)
178         {
179                 ti = proto_tree_add_item(tree, f.hf->header, tvb, *offset, -1, FALSE);
180                 fec_tree = proto_item_add_subtree(ti, f.ett->main);
181         } else
182         {
183                 ti = NULL;
184                 fec_tree = NULL;
185         }
186
187         /* FEC Encoding ID and FEC Instance ID processing */
188         if (f.fec->encoding_id_present)
189         {
190                 if (tree)
191                 {
192                         proto_tree_add_uint(fec_tree, f.hf->encoding_id, tvb, *offset, 0, f.fec->encoding_id);
193
194                         if (f.fec->encoding_id >= 128 && f.fec->instance_id_present)
195                                 proto_tree_add_uint(fec_tree, f.hf->instance_id, tvb, *offset, 0, f.fec->instance_id);
196                 }
197
198                 switch (f.fec->encoding_id)
199                 {
200                 case 0:
201                 case 130:
202                         f.fec->sbn = tvb_get_ntohs(tvb, *offset);
203                         f.fec->esi = tvb_get_ntohs(tvb, *offset+2);
204
205                         if (tree)
206                         {
207                                 proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 2, f.fec->sbn);
208                                 proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+2, 2, f.fec->esi);
209                         }
210
211                         f.fec->sbn_present = TRUE;
212                         f.fec->esi_present = TRUE;
213                         *offset += 4;
214                         break;
215
216                 case 2:
217                 case 128:
218                 case 132:
219                         f.fec->sbn = tvb_get_ntohl(tvb, *offset);
220                         f.fec->esi = tvb_get_ntohl(tvb, *offset+4);
221
222                         if (tree)
223                         {
224                                 proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 4, f.fec->sbn);
225                                 proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+4, 4, f.fec->esi);
226                         }
227
228                         f.fec->sbn_present = TRUE;
229                         f.fec->esi_present = TRUE;
230                         *offset += 8;
231                         break;
232
233                 case 129:
234                         f.fec->sbn = tvb_get_ntohl(tvb, *offset);
235                         f.fec->sbl = tvb_get_ntohs(tvb, *offset+4);
236                         f.fec->esi = tvb_get_ntohs(tvb, *offset+6);
237
238                         if (tree)
239                         {
240                                 proto_tree_add_uint(fec_tree, f.hf->sbn, tvb, *offset, 4, f.fec->sbn);
241                                 proto_tree_add_uint(fec_tree, f.hf->sbl, tvb, *offset+4, 2, f.fec->sbl);
242                                 proto_tree_add_uint(fec_tree, f.hf->esi, tvb, *offset+6, 2, f.fec->esi);
243                         }
244
245                         f.fec->sbn_present = TRUE;
246                         f.fec->sbl_present = TRUE;
247                         f.fec->esi_present = TRUE;
248                         *offset += 8;
249                         break;
250                 }
251         }
252         if (tree)
253                 proto_item_set_len(ti, *offset - offset_save);
254 }
255
256 void fec_dissector_free(struct _fec *fec _U_)
257 {
258
259 }
260
261 /* Preferences */
262 /* ----------- */
263
264 /* Set/Reset preferences to default values */
265 void fec_prefs_set_default(struct _fec_prefs *fec_prefs _U_)
266 {
267
268 }
269
270 /* Register preferences */
271 void fec_prefs_register(struct _fec_prefs *fec_prefs _U_, module_t *module _U_)
272 {
273
274 }