2cceb2a85e0fba9fe07ce7b4001d0b57bbb452e2
[obnox/wireshark/wip.git] / epan / dissectors / packet-dis-pdus.c
1 /* packet-dis-pdus.c
2  * Routines and definitions for DIS PDU parsing.
3  * Copyright 2005, Scientific Research Corporation
4  * Initial implementation by Jeremy Ouellette <jouellet@scires.com>
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <string.h>
32 #include "packet-dis-pdus.h"
33 #include "packet-dis-fields.h"
34 #include "packet-dis-enums.h"
35
36 #define DIS_PDU_MAX_VARIABLE_PARAMETERS 16
37 #define DIS_PDU_MAX_VARIABLE_RECORDS 16
38 #define DIS_PDU_MAX_ELECTROMAGNETIC_EMISSION_SYSTEMS 16
39
40
41 gint ettVariableParameters[DIS_PDU_MAX_VARIABLE_PARAMETERS];
42 gint ettVariableRecords[DIS_PDU_MAX_VARIABLE_RECORDS];
43
44 gint ettFixedData = -1;
45 gint ettVariableData = -1;
46
47 /* DIS Entity Information / Interaction PDUs
48  */
49 DIS_ParserNode DIS_PARSER_ENTITY_STATE_PDU[] =
50 {
51     { DIS_FIELDTYPE_ENTITY_ID,               "Entity ID",0,0,0,0 },
52     { DIS_FIELDTYPE_FORCE_ID,                "Force ID",0,0,0,0 },
53     { DIS_FIELDTYPE_NUM_ARTICULATION_PARAMS, "Number of Articulation Parameters",0,0,0,&numVariable },
54     { DIS_FIELDTYPE_ENTITY_TYPE,             "Entity Type",0,0,0,0 },
55     { DIS_FIELDTYPE_ENTITY_TYPE,             "Alternative Entity Type",0,0,0,0 },
56     { DIS_FIELDTYPE_LINEAR_VELOCITY,         "Entity Linear Velocity",0,0,0,0 },
57     { DIS_FIELDTYPE_LOCATION_WORLD,          "Entity Location",0,0,0,0 },
58     { DIS_FIELDTYPE_ORIENTATION,             "Entity Orientation",0,0,0,0 },
59     { DIS_FIELDTYPE_APPEARANCE,              "Entity Appearance",0,0,0,0 },
60     { DIS_FIELDTYPE_DEAD_RECKONING_PARAMS,   "Dead Reckoning Parameters",0,0,0,0 },
61     { DIS_FIELDTYPE_ENTITY_MARKING,          "Entity Marking",0,0,0,0 },
62     { DIS_FIELDTYPE_CAPABILITIES,            "Capabilities",0,0,0,0 },
63     { DIS_FIELDTYPE_VARIABLE_PARAMETERS,     "Variable Parameter",0,0,0,0 },
64     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
65 };
66
67 /* DIS Distributed Emission Regeneration PDUs
68  */
69 DIS_ParserNode DIS_PARSER_ELECTROMAGNETIC_EMISSION_PDU[] =
70 {
71     { DIS_FIELDTYPE_ENTITY_ID,               "Emitting Entity ID",0,0,0,0 },
72     { DIS_FIELDTYPE_ENTITY_ID,               "Event ID",0,0,0,0 },
73     { DIS_FIELDTYPE_UINT8,                   "State Update Indicator",0,0,0,0 },
74     { DIS_FIELDTYPE_NUM_ELECTROMAGNETIC_EMISSION_SYSTEMS, "Number of Systems (N)",0,0,0,&numVariable },
75     { DIS_FIELDTYPE_PAD16,                   "Padding",0,0,0,0 },
76     { DIS_FIELDTYPE_ELECTROMAGNETIC_EMISSION_SYSTEM, "Emission System",0,0,0,0 },
77     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
78 };
79
80
81 /* DIS Radio Communications protocol (RCP) family PDUs
82  */
83 DIS_ParserNode DIS_PARSER_TRANSMITTER_PDU[] =
84 {
85     { DIS_FIELDTYPE_ENTITY_ID,                    "Entity ID",0,0,0,0 },
86     { DIS_FIELDTYPE_RADIO_ID,                     "Radio ID",0,0,0,&radioID },
87     { DIS_FIELDTYPE_RADIO_ENTITY_TYPE,            "Radio Entity Type",0,0,0,0 },
88     { DIS_FIELDTYPE_RADIO_TRANSMIT_STATE,         "Radio Transmit State",0,0,0,&disRadioTransmitState },
89     { DIS_FIELDTYPE_RADIO_INPUT_SOURCE,           "Radio Input Source",0,0,0,0 },
90     { DIS_FIELDTYPE_PAD16,                        "Padding",0,0,0,0 },
91     { DIS_FIELDTYPE_ANTENNA_LOCATION,             "Antenna Location",0,0,0,0 },
92     { DIS_FIELDTYPE_REL_ANTENNA_LOCATON,          "Relative Antenna Location",0,0,0,0 },
93     { DIS_FIELDTYPE_ANTENNA_PATTERN_TYPE,         "Antenna Pattern Type",0,0,0,&disAntennaPattern },
94     { DIS_FIELDTYPE_ANTENNA_PATTERN_LENGTH,       "Antenna Pattern Length",0,0,0,0 },
95     { DIS_FIELDTYPE_TRANSMIT_FREQUENCY,           "Transmit Frequency",0,0,0,0 },
96     { DIS_FIELDTYPE_FLOAT32,                      "Transmit Frequency Bandwidth",0,0,0,0 },
97     { DIS_FIELDTYPE_FLOAT32,                      "Transmit Power",0,0,0,0 },
98     { DIS_FIELDTYPE_MODULATION_TYPE,              "Modulation Type",0,0,0,0 },
99     { DIS_FIELDTYPE_CRYPTO_SYSTEM,                "Crypto System",0,0,0,0 },
100     { DIS_FIELDTYPE_CRYPTO_KEY_ID,                "Crypto Key ID",0,0,0,0 },
101     { DIS_FIELDTYPE_MODULATION_PARAMETER_LENGTH,  "Modulation Parameter Length",0,0,0,&modulationParamLength },
102     { DIS_FIELDTYPE_PAD24,                        "Padding",0,0,0,0 },
103     { DIS_FIELDTYPE_MODULATION_PARAMETERS,        "Modulation Parameters",0,0,0,0 },
104     /* need to finish decoding this PDU */
105     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
106 };
107
108 DIS_ParserNode DIS_PARSER_SIGNAL_PDU[] =
109 {
110     { DIS_FIELDTYPE_ENTITY_ID,               "Entity ID",0,0,0,0 },
111     { DIS_FIELDTYPE_RADIO_ID,                "Radio ID",0,0,0,&radioID },
112     { DIS_FIELDTYPE_ENCODING_SCHEME,         "Encoding Scheme",0,0,0,&encodingScheme },
113     { DIS_FIELDTYPE_TDL_TYPE,                "TDL Type",0,0,0,0 },
114     { DIS_FIELDTYPE_SAMPLE_RATE,             "Sample Rate",0,0,0,0 },
115     { DIS_FIELDTYPE_DATA_LENGTH,             "Data Length",0,0,0,0 },
116     { DIS_FIELDTYPE_NUMBER_OF_SAMPLES,       "Number of Samples",0,0,0,&numSamples },
117     { DIS_FIELDTYPE_RADIO_DATA,              "Radio Data",0,0,0,0 },
118     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
119 };
120
121 /* DIS Warfare PDUs
122  */
123 DIS_ParserNode DIS_PARSER_FIRE_PDU[] =
124 {
125     { DIS_FIELDTYPE_ENTITY_ID,        "Firing Entity ID",0,0,0,0 },
126     { DIS_FIELDTYPE_ENTITY_ID,        "Target Entity ID",0,0,0,0 },
127     { DIS_FIELDTYPE_ENTITY_ID,        "Munition ID",0,0,0,0 },
128     { DIS_FIELDTYPE_EVENT_ID,         "Event ID",0,0,0,0 },
129     { DIS_FIELDTYPE_UINT32,           "Fire Mission Index",0,0,0,0 },
130     { DIS_FIELDTYPE_LOCATION_WORLD,   "Location in World Coordinates",0,0,0,0 },
131     { DIS_FIELDTYPE_BURST_DESCRIPTOR, "Burst Descriptor",0,0,0,0 },
132     { DIS_FIELDTYPE_LINEAR_VELOCITY,  "Velocity",0,0,0,0 },
133     { DIS_FIELDTYPE_FLOAT32,          "Range",0,0,0,0 },
134     { DIS_FIELDTYPE_END,              NULL,0,0,0,0 }
135 };
136
137 DIS_ParserNode DIS_PARSER_DETONATION_PDU[] =
138 {
139     { DIS_FIELDTYPE_ENTITY_ID,               "Firing Entity ID",0,0,0,0 },
140     { DIS_FIELDTYPE_ENTITY_ID,               "Target Entity ID",0,0,0,0 },
141     { DIS_FIELDTYPE_ENTITY_ID,               "Munition ID",0,0,0,0 },
142     { DIS_FIELDTYPE_EVENT_ID,                "Event ID",0,0,0,0 },
143     { DIS_FIELDTYPE_LINEAR_VELOCITY,         "Velocity",0,0,0,0 },
144     { DIS_FIELDTYPE_LOCATION_WORLD,          "Location in World Coordinates",0,0,0,0 },
145     { DIS_FIELDTYPE_BURST_DESCRIPTOR,        "Burst Descriptor",0,0,0,0 },
146     { DIS_FIELDTYPE_LOCATION_ENTITY,         "Location in Entity Coordinates",0,0,0,0 },
147     { DIS_FIELDTYPE_DETONATION_RESULT,       "Detonation Result",0,0,0,0 },
148     { DIS_FIELDTYPE_NUM_ARTICULATION_PARAMS, "Number of Articulation Parameters",0,0,0,&numVariable },
149     { DIS_FIELDTYPE_PAD16,                   "Padding",0,0,0,0 },
150     { DIS_FIELDTYPE_VARIABLE_PARAMETERS,     "Variable Parameter",0,0,0,0 },
151     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
152 };
153
154 /* DIS Simulation Management PDUs
155  */
156 DIS_ParserNode DIS_PARSER_START_RESUME_PDU[] =
157 {
158     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
159     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
160     { DIS_FIELDTYPE_CLOCK_TIME,              "Real World Time",0,0,0,0 },
161     { DIS_FIELDTYPE_CLOCK_TIME,              "Simulation Time",0,0,0,0 },
162     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
163     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
164 };
165
166 DIS_ParserNode DIS_PARSER_STOP_FREEZE_PDU[] =
167 {
168     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
169     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
170     { DIS_FIELDTYPE_CLOCK_TIME,              "Real World Time",0,0,0,0 },
171     { DIS_FIELDTYPE_REASON,                  "Reason",0,0,0,0 },
172     { DIS_FIELDTYPE_FROZEN_BEHAVIOR,         "Frozen Behavior",0,0,0,0 },
173     { DIS_FIELDTYPE_PAD16,                   "Padding",0,0,0,0 },
174     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
175     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
176 };
177
178 DIS_ParserNode DIS_PARSER_ACKNOWLEDGE_PDU[] =
179 {
180     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
181     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
182     { DIS_FIELDTYPE_ACKNOWLEDGE_FLAG,        "Acknowledge Flag",0,0,0,0 },
183     { DIS_FIELDTYPE_RESPONSE_FLAG,           "Response Flag",0,0,0,0 },
184     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
185     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
186 };
187
188 DIS_ParserNode DIS_PARSER_ACTION_REQUEST_PDU[] =
189 {
190     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
191     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
192     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
193     { DIS_FIELDTYPE_ACTION_ID,               "Action ID",0,0,0,0 },
194     { DIS_FIELDTYPE_NUM_FIXED_DATA,          "Number of Fixed Data Fields",0,0,0,&numFixed },
195     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,       "Number of Variable Data Fields",0,0,0,&numVariable },
196     { DIS_FIELDTYPE_FIXED_DATUMS,            "Fixed data",0,0,0,0 },
197     { DIS_FIELDTYPE_VARIABLE_DATUMS,         "Variable data",0,0,0,0 },
198     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
199 };
200
201 DIS_ParserNode DIS_PARSER_ACTION_RESPONSE_PDU[] =
202 {
203     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
204     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
205     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
206     { DIS_FIELDTYPE_REQUEST_STATUS,          "Request Status",0,0,0,0 },
207     { DIS_FIELDTYPE_NUM_FIXED_DATA,          "Number of Fixed Data Fields",0,0,0,&numFixed },
208     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,       "Number of Variable Data Fields",0,0,0,&numVariable },
209     { DIS_FIELDTYPE_FIXED_DATUMS,            "Fixed data",0,0,0,0 },
210     { DIS_FIELDTYPE_VARIABLE_DATUMS,         "Variable data",0,0,0,0 },
211     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
212 };
213
214 DIS_ParserNode DIS_PARSER_DATA_PDU[] =
215 {
216     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
217     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
218     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
219     { DIS_FIELDTYPE_PAD32,                   "Padding",0,0,0,0 },
220     { DIS_FIELDTYPE_NUM_FIXED_DATA,          "Number of Fixed Data Fields",0,0,0,&numFixed },
221     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,       "Number of Variable Data Fields",0,0,0,&numVariable },
222     { DIS_FIELDTYPE_FIXED_DATUMS,            "Fixed data",0,0,0,0 },
223     { DIS_FIELDTYPE_VARIABLE_DATUMS,         "Variable data",0,0,0,0 },
224     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
225 };
226
227 DIS_ParserNode DIS_PARSER_DATA_QUERY_PDU[] =
228 {
229     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
230     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
231     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
232     { DIS_FIELDTYPE_TIME_INTERVAL,           "Time interval",0,0,0,0 },
233     { DIS_FIELDTYPE_NUM_FIXED_DATA,          "Number of Fixed Datum Ids",0,0,0,&numFixed },
234     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,       "Number of Variable Datum Ids",0,0,0,&numVariable },
235     { DIS_FIELDTYPE_FIXED_DATUM_IDS,         "Fixed datum ids",0,0,0,0 },
236     { DIS_FIELDTYPE_VARIABLE_DATUM_IDS,      "Variable datum ids",0,0,0,0 },
237     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
238 };
239
240 DIS_ParserNode DIS_PARSER_COMMENT_PDU[] =
241 {
242     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
243     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
244     { DIS_FIELDTYPE_NUM_FIXED_DATA,          "Number of Fixed Data Fields",0,0,0,&numFixed },
245     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,       "Number of Variable Data Fields",0,0,0,&numVariable },
246     { DIS_FIELDTYPE_FIXED_DATUMS,            "Fixed data",0,0,0,0 },
247     { DIS_FIELDTYPE_VARIABLE_DATUMS,         "Variable data",0,0,0,0 },
248     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
249 };
250
251 DIS_ParserNode DIS_PARSER_SIMAN_ENTITY_PDU[] =
252 {
253     { DIS_FIELDTYPE_ENTITY_ID,               "Originating Entity ID",0,0,0,0 },
254     { DIS_FIELDTYPE_ENTITY_ID,               "Receiving Entity ID",0,0,0,0 },
255     { DIS_FIELDTYPE_REQUEST_ID,              "Request ID",0,0,0,0 },
256     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
257 };
258
259 /* DIS Simulation Management with Reliability PDUs
260  */
261 DIS_ParserNode DIS_PARSER_START_RESUME_R_PDU[] =
262 {
263     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
264     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
265     { DIS_FIELDTYPE_CLOCK_TIME,                   "Real World Time",0,0,0,0 },
266     { DIS_FIELDTYPE_CLOCK_TIME,                   "Simulation Time",0,0,0,0 },
267     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
268     { DIS_FIELDTYPE_PAD8,                         "Padding",3,0,0,0 },
269     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
270     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
271 };
272
273 DIS_ParserNode DIS_PARSER_STOP_FREEZE_R_PDU[] =
274 {
275     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
276     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
277     { DIS_FIELDTYPE_CLOCK_TIME,                   "Real World Time",0,0,0,0 },
278     { DIS_FIELDTYPE_REASON,                       "Reason",0,0,0,0 },
279     { DIS_FIELDTYPE_FROZEN_BEHAVIOR,              "Frozen Behavior",0,0,0,0 },
280     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
281     { DIS_FIELDTYPE_PAD8,                         "Padding",0,0,0,0 },
282     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
283     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
284 };
285
286 DIS_ParserNode DIS_PARSER_ACTION_REQUEST_R_PDU[] =
287 {
288     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
289     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
290     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
291     { DIS_FIELDTYPE_PAD8,                         "Padding",3,0,0,0 },
292     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
293     { DIS_FIELDTYPE_ACTION_ID,                    "Action ID",0,0,0,0 },
294     { DIS_FIELDTYPE_NUM_FIXED_DATA,               "Number of Fixed Data Fields",0,0,0,&numFixed },
295     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,            "Number of Variable Data Fields",0,0,0,&numVariable },
296     { DIS_FIELDTYPE_FIXED_DATUMS,                 "Fixed data",0,0,0,0 },
297     { DIS_FIELDTYPE_VARIABLE_DATUMS,              "Variable data",0,0,0,0 },
298     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
299 };
300
301 DIS_ParserNode DIS_PARSER_DATA_R_PDU[] =
302 {
303     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
304     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
305     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
306     { DIS_FIELDTYPE_PAD8,                         "Padding",3,0,0,0 },
307     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
308     { DIS_FIELDTYPE_NUM_FIXED_DATA,               "Number of Fixed Data Fields",0,0,0,&numFixed },
309     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,            "Number of Variable Data Fields",0,0,0,&numVariable },
310     { DIS_FIELDTYPE_FIXED_DATUMS,                 "Fixed data",0,0,0,0 },
311     { DIS_FIELDTYPE_VARIABLE_DATUMS,              "Variable data",0,0,0,0 },
312     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
313 };
314
315 DIS_ParserNode DIS_PARSER_DATA_QUERY_R_PDU[] =
316 {
317     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
318     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
319     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
320     { DIS_FIELDTYPE_PAD8,                         "Padding",3,0,0,0 },
321     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
322     { DIS_FIELDTYPE_TIME_INTERVAL,                "Time interval",0,0,0,0 },
323     { DIS_FIELDTYPE_NUM_FIXED_DATA,               "Number of Fixed Datum Ids",0,0,0,&numFixed },
324     { DIS_FIELDTYPE_NUM_VARIABLE_DATA,            "Number of Variable Datum Ids",0,0,0,&numVariable },
325     { DIS_FIELDTYPE_FIXED_DATUM_IDS,              "Fixed datum ids",0,0,0,0 },
326     { DIS_FIELDTYPE_VARIABLE_DATUM_IDS,           "Variable datum ids",0,0,0,0 },
327     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
328 };
329
330 DIS_ParserNode DIS_PARSER_SIMAN_ENTITY_R_PDU[] =
331 {
332     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
333     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
334     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
335     { DIS_FIELDTYPE_PAD8,                         "Padding",3,0,0,0 },
336     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
337     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
338 };
339
340 /* DIS Experimental V-DIS PDUs
341  */
342 DIS_ParserNode DIS_PARSER_APPLICATION_CONTROL_PDU[] =
343 {
344     { DIS_FIELDTYPE_ENTITY_ID,                    "Originating Entity ID",0,0,0,0 },
345     { DIS_FIELDTYPE_ENTITY_ID,                    "Receiving Entity ID",0,0,0,0 },
346     { DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE, "Reliability",0,0,0,0 },
347     { DIS_FIELDTYPE_UINT8,                        "Time Interval",0,0,0,0 },
348     { DIS_FIELDTYPE_CONTROL_ID,                   "Control ID",0,0,0,0 },
349     { DIS_FIELDTYPE_PAD8,                         "Padding",0,0,0,0 },
350     { DIS_FIELDTYPE_APPLICATION_TYPE,             "Originating App Type",0,0,0,0 },
351     { DIS_FIELDTYPE_APPLICATION_TYPE,             "Receiving App Type",0,0,0,0 },
352     { DIS_FIELDTYPE_REQUEST_ID,                   "Request ID",0,0,0,0 },
353     { DIS_FIELDTYPE_UINT8,                        "Number of Parts",0,0,0,0 },
354     { DIS_FIELDTYPE_UINT8,                        "Current Part",0,0,0,0 },
355     { DIS_FIELDTYPE_UINT16,                       "Number of Variable Records",0,0,0,&numVariable },
356     { DIS_FIELDTYPE_VARIABLE_RECORDS,             "Record",0,0,0,0 },
357     { DIS_FIELDTYPE_END,                          NULL,0,0,0,0 }
358 };
359
360 /* Persistent Object (PO) Family PDU parsers
361  */
362 DIS_ParserNode DIS_PARSER_SIMULATOR_PRESENT_PO_PDU[] =
363 {
364     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Simulator",0,0,0,0 },
365     { DIS_FIELDTYPE_UINT16,                  "Simulator Type",0,0,0,0 },
366     { DIS_FIELDTYPE_UINT32,                  "Database Sequence Number",0,0,0,0 },
367     { DIS_FIELDTYPE_UINT32,                  "Simulator Load",0,0,0,0 },
368     { DIS_FIELDTYPE_FLOAT32,                 "Simulation Load",0,0,0,0 },
369     { DIS_FIELDTYPE_UINT32,                  "Time",0,0,0,0 },
370     { DIS_FIELDTYPE_UINT32,                  "Packets Sent",0,0,0,0 },
371     { DIS_FIELDTYPE_UINT16,                  "Unit Database Version",0,0,0,0 },
372     { DIS_FIELDTYPE_UINT16,                  "Relative Battle Scheme",0,0,0,0 },
373     { DIS_FIELDTYPE_FIXED_LEN_STR,           "Terrain Name",32,0,0,0 },
374     { DIS_FIELDTYPE_UINT16,                  "Terrain Version",0,0,0,0 },
375     { DIS_FIELDTYPE_FIXED_LEN_STR,           "Host Name",32,0,0,0 },
376     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
377 };
378
379 DIS_ParserNode DIS_PARSER_DESCRIBE_OBJECT_PO_PDU[] =
380 {
381     { DIS_FIELDTYPE_UINT32,                  "Database Sequence Number",0,0,0,0 },
382     { DIS_FIELDTYPE_ENTITY_ID,               "Object ID",0,0,0,0 },
383     { DIS_FIELDTYPE_ENTITY_ID,               "World State ID",0,0,0,0 },
384     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Owner",0,0,0,0 },
385     { DIS_FIELDTYPE_UINT16,                  "Sequence Number",0,0,0,0 },
386     { DIS_FIELDTYPE_PERSISTENT_OBJECT_CLASS, "Object Class",0,0,0,0 },
387     { DIS_FIELDTYPE_UINT8,                   "Missing From World State",0,0,0,0 },
388     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
389 };
390
391 DIS_ParserNode DIS_PARSER_OBJECTS_PRESENT_PO_PDU[] =
392 {
393     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Owner",0,0,0,0 },
394     { DIS_FIELDTYPE_ENTITY_ID,               "World State ID",0,0,0,0 },
395     { DIS_FIELDTYPE_UINT8,                   "Object Count",0,0,0,0 },
396     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
397 };
398
399 DIS_ParserNode DIS_PARSER_OBJECT_REQUEST_PO_PDU[] =
400 {
401     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Requesting Simulator",0,0,0,0 },
402     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Object Owner",0,0,0,0 },
403     { DIS_FIELDTYPE_ENTITY_ID,               "World State ID",0,0,0,0 },
404     { DIS_FIELDTYPE_UINT8,                   "Object Count",0,0,0,0 },
405     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
406 };
407
408 DIS_ParserNode DIS_PARSER_DELETE_OBJECTS_PO_PDU[] =
409 {
410     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Requesting Simulator",0,0,0,0 },
411     { DIS_FIELDTYPE_UINT8,                   "Object Count",0,0,0,0 },
412     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
413 };
414
415 DIS_ParserNode DIS_PARSER_SET_WORLD_STATE_PO_PDU[] =
416 {
417     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Requesting Simulator",0,0,0,0 },
418     { DIS_FIELDTYPE_FLOAT32,                 "Clock Rate",0,0,0,0 },
419     { DIS_FIELDTYPE_UINT32,                  "Seconds Since 1970",0,0,0,0 },
420     { DIS_FIELDTYPE_ENTITY_ID,               "World State ID",0,0,0,0 },
421     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
422 };
423
424 DIS_ParserNode DIS_PARSER_NOMINATION_PO_PDU[] =
425 {
426     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Nominated Simulator",0,0,0,0 },
427     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Nominating Simulator",0,0,0,0 },
428     { DIS_FIELDTYPE_SIMULATION_ADDRESS,      "Missing Simulator",0,0,0,0 },
429     { DIS_FIELDTYPE_END,                     NULL,0,0,0,0 }
430 };
431
432 /* Initialize the parsers for each PDU type and the standard DIS header.
433  */
434 void initializeParsers(void)
435 {
436     gint *ett[DIS_PDU_MAX_VARIABLE_PARAMETERS+DIS_PDU_MAX_VARIABLE_RECORDS+2];
437     int   i, ett_index;
438
439     initializeParser(DIS_FIELDS_PDU_HEADER);
440
441     /* DIS Entity Information / Interaction PDUs */
442     initializeParser(DIS_PARSER_ENTITY_STATE_PDU);
443
444     /* DIS Distributed Emission Regeneration PDUs */
445     initializeParser(DIS_PARSER_ELECTROMAGNETIC_EMISSION_PDU);
446
447     /* DIS Radio Communications protocol (RCP) family PDUs */
448     initializeParser(DIS_PARSER_TRANSMITTER_PDU);
449     initializeParser(DIS_PARSER_SIGNAL_PDU);
450
451     /* DIS Warfare PDUs */
452     initializeParser(DIS_PARSER_FIRE_PDU);
453     initializeParser(DIS_PARSER_DETONATION_PDU);
454
455     /* DIS Simulation Management PDUs */
456     initializeParser(DIS_PARSER_START_RESUME_PDU);
457     initializeParser(DIS_PARSER_STOP_FREEZE_PDU);
458     initializeParser(DIS_PARSER_ACKNOWLEDGE_PDU);
459     initializeParser(DIS_PARSER_ACTION_REQUEST_PDU);
460     initializeParser(DIS_PARSER_ACTION_RESPONSE_PDU);
461     initializeParser(DIS_PARSER_DATA_PDU);
462     initializeParser(DIS_PARSER_DATA_QUERY_PDU);
463     initializeParser(DIS_PARSER_COMMENT_PDU);
464     initializeParser(DIS_PARSER_SIMAN_ENTITY_PDU);
465
466     /* DIS Simulation Management with Reliability PDUs */
467     initializeParser(DIS_PARSER_START_RESUME_R_PDU);
468     initializeParser(DIS_PARSER_STOP_FREEZE_R_PDU);
469     initializeParser(DIS_PARSER_ACTION_REQUEST_R_PDU);
470     initializeParser(DIS_PARSER_DATA_R_PDU);
471     initializeParser(DIS_PARSER_DATA_QUERY_R_PDU);
472     initializeParser(DIS_PARSER_SIMAN_ENTITY_R_PDU);
473
474     /* DIS Experimental V-DIS PDUs */
475     initializeParser(DIS_PARSER_APPLICATION_CONTROL_PDU);
476
477     /* Initialize the Persistent Object PDUs */
478     initializeParser(DIS_FIELDS_PERSISTENT_OBJECT_HEADER);
479     initializeParser(DIS_PARSER_DESCRIBE_OBJECT_PO_PDU);
480     initializeParser(DIS_PARSER_SIMULATOR_PRESENT_PO_PDU);
481     initializeParser(DIS_PARSER_OBJECTS_PRESENT_PO_PDU);
482     initializeParser(DIS_PARSER_OBJECT_REQUEST_PO_PDU);
483     initializeParser(DIS_PARSER_DELETE_OBJECTS_PO_PDU);
484     initializeParser(DIS_PARSER_SET_WORLD_STATE_PO_PDU);
485     initializeParser(DIS_PARSER_NOMINATION_PO_PDU);
486
487     /* Initialize the ett array */
488     ett_index = 0;
489     for (i=0; i<DIS_PDU_MAX_VARIABLE_PARAMETERS; i++, ett_index++)
490     {
491         ettVariableParameters[i] = -1;
492         ett[ett_index] = &ettVariableParameters[i];
493     }
494     for (i=0; i<DIS_PDU_MAX_VARIABLE_RECORDS; i++, ett_index++)
495     {
496         ettVariableRecords[i] = -1;
497         ett[ett_index] = &ettVariableRecords[i];
498     }
499     ett[ett_index++] = &ettFixedData;
500     ett[ett_index++] = &ettVariableData;
501     proto_register_subtree_array(ett, array_length(ett));
502 }
503
504 /* Create a specific subtree for a PDU or a composite PDU field.
505  */
506 DIS_ParserNode *createSubtree(DIS_ParserNode parserNodes[], gint *ettVar)
507 {
508     guint fieldIndex = 0;
509     guint fieldCount;
510     gint *ett[1];
511     DIS_ParserNode *newSubtree;
512
513     while (parserNodes[fieldIndex].fieldType != DIS_FIELDTYPE_END)
514     {
515         ++fieldIndex;
516     }
517
518     fieldCount = fieldIndex + 1;
519
520     newSubtree = (DIS_ParserNode*)g_malloc(sizeof(DIS_ParserNode) * fieldCount);
521
522     memcpy(newSubtree, parserNodes, sizeof(DIS_ParserNode) * fieldCount);
523
524     initializeParser(newSubtree);
525
526     *ettVar = -1;
527     ett[0] = ettVar;
528     proto_register_subtree_array(ett, array_length(ett));
529
530     return newSubtree;
531 }
532
533 /* Initialize an array of parser nodes.
534  */
535 void initializeParser(DIS_ParserNode parserNodes[])
536 {
537     guint parserIndex = 0;
538
539     /* Create the parser subtrees for each of the composite field types.
540      */
541     while (parserNodes[parserIndex].fieldType != DIS_FIELDTYPE_END)
542     {
543         switch (parserNodes[parserIndex].fieldType)
544         {
545         /* Bit fields */
546         case DIS_FIELDTYPE_APPEARANCE:
547             parserNodes[parserIndex].children = createSubtree(
548                 DIS_FIELDS_NONE,
549                 &parserNodes[parserIndex].ettVar);
550             break;
551
552         /* Composite types */
553         case DIS_FIELDTYPE_MOD_PARAMS_CCTT_SINCGARS:
554             parserNodes[parserIndex].children = createSubtree(
555                 DIS_FIELDS_MOD_PARAMS_CCTT_SINCGARS,
556                 &parserNodes[parserIndex].ettVar);
557             break;
558         case DIS_FIELDTYPE_MOD_PARAMS_JTIDS_MIDS:
559             parserNodes[parserIndex].children = createSubtree(
560                 DIS_FIELDS_MOD_PARAMS_JTIDS_MIDS,
561                 &parserNodes[parserIndex].ettVar);
562             break;
563
564         case DIS_FIELDTYPE_BURST_DESCRIPTOR:
565             parserNodes[parserIndex].children = createSubtree(
566                 DIS_FIELDS_BURST_DESCRIPTOR,
567                 &parserNodes[parserIndex].ettVar);
568             break;
569         case DIS_FIELDTYPE_CLOCK_TIME:
570             parserNodes[parserIndex].children = createSubtree(
571                 DIS_FIELDS_CLOCK_TIME,
572                 &parserNodes[parserIndex].ettVar);
573             break;
574         case DIS_FIELDTYPE_ENTITY_ID:
575             parserNodes[parserIndex].children = createSubtree(
576                 DIS_FIELDS_ENTITY_ID,
577                 &parserNodes[parserIndex].ettVar);
578             break;
579         case DIS_FIELDTYPE_ENTITY_TYPE:
580             parserNodes[parserIndex].children = createSubtree(
581                 DIS_FIELDS_ENTITY_TYPE,
582                 &parserNodes[parserIndex].ettVar);
583             break;
584         case DIS_FIELDTYPE_RADIO_ENTITY_TYPE:
585             parserNodes[parserIndex].children = createSubtree(
586                 DIS_FIELDS_RADIO_ENTITY_TYPE,
587                 &parserNodes[parserIndex].ettVar);
588             break;
589         case DIS_FIELDTYPE_EVENT_ID:
590             parserNodes[parserIndex].children = createSubtree(
591                 DIS_FIELDS_EVENT_ID,
592                 &parserNodes[parserIndex].ettVar);
593             break;
594         case DIS_FIELDTYPE_ORIENTATION:
595             parserNodes[parserIndex].children = createSubtree(
596                 DIS_FIELDS_ORIENTATION,
597                 &parserNodes[parserIndex].ettVar);
598             break;
599         case DIS_FIELDTYPE_SIMULATION_ADDRESS:
600             parserNodes[parserIndex].children = createSubtree(
601                 DIS_FIELDS_SIMULATION_ADDRESS,
602                 &parserNodes[parserIndex].ettVar);
603             break;
604         case DIS_FIELDTYPE_LINEAR_VELOCITY:
605         case DIS_FIELDTYPE_LOCATION_ENTITY:
606         case DIS_FIELDTYPE_REL_ANTENNA_LOCATON:
607         case DIS_FIELDTYPE_VECTOR_32:
608             parserNodes[parserIndex].children = createSubtree(
609                 DIS_FIELDS_VECTOR_FLOAT_32,
610                 &parserNodes[parserIndex].ettVar);
611             break;
612         case DIS_FIELDTYPE_LOCATION_WORLD:
613         case DIS_FIELDTYPE_ANTENNA_LOCATION:
614         case DIS_FIELDTYPE_VECTOR_64:
615             parserNodes[parserIndex].children = createSubtree(
616                 DIS_FIELDS_VECTOR_FLOAT_64,
617                 &parserNodes[parserIndex].ettVar);
618             break;
619         case DIS_FIELDTYPE_MODULATION_TYPE:
620             parserNodes[parserIndex].children = createSubtree(
621                 DIS_FIELDS_MODULATION_TYPE,
622                 &parserNodes[parserIndex].ettVar);
623             break;
624         case DIS_FIELDTYPE_ELECTROMAGNETIC_EMISSION_SYSTEM_BEAM:
625             parserNodes[parserIndex].children = createSubtree(
626                 DIS_FIELDS_VR_ELECTROMAGNETIC_EMISSION_SYSTEM_BEAM,
627                 &parserNodes[parserIndex].ettVar);
628             break;
629         case DIS_FIELDTYPE_ELECTROMAGNETIC_EMISSION_SYSTEM:
630             parserNodes[parserIndex].children = createSubtree(
631                 DIS_FIELDS_VR_ELECTROMAGNETIC_EMISSION_SYSTEM,
632                 &parserNodes[parserIndex].ettVar);
633             break;
634         case DIS_FIELDTYPE_EMITTER_SYSTEM:
635             parserNodes[parserIndex].children = createSubtree(
636                 DIS_FIELDS_EMITTER_SYSTEM,
637                 &parserNodes[parserIndex].ettVar);
638             break;
639         case DIS_FIELDTYPE_FUNDAMENTAL_PARAMETER_DATA:
640             parserNodes[parserIndex].children = createSubtree(
641                 DIS_FIELDS_FUNDAMENTAL_PARAMETER_DATA,
642                 &parserNodes[parserIndex].ettVar);
643             break;
644         case DIS_FIELDTYPE_TRACK_JAM:
645             parserNodes[parserIndex].children = createSubtree(
646                 DIS_FIELDS_TRACK_JAM,
647                 &parserNodes[parserIndex].ettVar);
648             break;
649         /* Array records */
650         case DIS_FIELDTYPE_FIXED_DATUMS:
651             parserNodes[parserIndex].children = createSubtree(
652                 DIS_FIELDS_FIXED_DATUM,
653                 &parserNodes[parserIndex].ettVar);
654             break;
655         case DIS_FIELDTYPE_VARIABLE_DATUMS:
656             parserNodes[parserIndex].children = createSubtree(
657                 DIS_FIELDS_VARIABLE_DATUM,
658                 &parserNodes[parserIndex].ettVar);
659             break;
660         case DIS_FIELDTYPE_FIXED_DATUM_IDS:
661         case DIS_FIELDTYPE_VARIABLE_DATUM_IDS:
662             parserNodes[parserIndex].children = createSubtree(
663                 DIS_FIELDS_DATUM_IDS,
664                 &parserNodes[parserIndex].ettVar);
665             break;
666         case DIS_FIELDTYPE_VARIABLE_PARAMETERS:
667             parserNodes[parserIndex].children = createSubtree(
668                 DIS_FIELDS_VP_TYPE,
669                 &parserNodes[parserIndex].ettVar);
670             break;
671         case DIS_FIELDTYPE_VARIABLE_RECORDS:
672             parserNodes[parserIndex].children = createSubtree(
673                 DIS_FIELDS_VR_TYPE,
674                 &parserNodes[parserIndex].ettVar);
675             break;
676         default:
677             break;
678         }
679         ++parserIndex;
680     }
681 }
682
683 /* Parse packet data based on a specified array of DIS_ParserNodes.
684  */
685 gint parseFields(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNodes[])
686 {
687     guint        fieldIndex     = 0;
688     guint        fieldRepeatLen = 0;
689     guint64      uintVal        = 0;
690     proto_item  *pi             = NULL;
691     proto_tree  *sub_tree       = NULL;
692     tvbuff_t    *newtvb         = NULL;
693     gint         length         = 0;
694     guint16 spread_spectrum     = 0;
695
696
697     length = tvb_length_remaining(tvb, offset);
698
699     while ((parserNodes[fieldIndex].fieldType != DIS_FIELDTYPE_END)
700             && (length > 0 ) )
701     {
702         proto_item *newField = 0;
703
704         fieldRepeatLen = (guint) ((parserNodes[fieldIndex].fieldRepeatLen > 1) ?
705             parserNodes[fieldIndex].fieldRepeatLen : 1);
706
707         switch(parserNodes[fieldIndex].fieldType)
708         {
709         /* basic numeric types */
710         case DIS_FIELDTYPE_INT8:
711             offset = parseField_Int(tvb, tree, offset,
712                 parserNodes[fieldIndex], 1);
713             break;
714         case DIS_FIELDTYPE_INT16:
715             offset = parseField_Int(tvb, tree, offset,
716                 parserNodes[fieldIndex], 2);
717             break;
718         case DIS_FIELDTYPE_INT32:
719             offset = parseField_Int(tvb, tree, offset,
720                 parserNodes[fieldIndex], 4);
721             break;
722         case DIS_FIELDTYPE_INT64:
723             offset = parseField_Int(tvb, tree, offset,
724                 parserNodes[fieldIndex], 8);
725             break;
726         case DIS_FIELDTYPE_UINT8:
727             offset = parseField_UInt(tvb, tree, offset,
728                 parserNodes[fieldIndex], 1);
729             break;
730         case DIS_FIELDTYPE_UINT16:
731             offset = parseField_UInt(tvb, tree, offset,
732                 parserNodes[fieldIndex], 2);
733             break;
734         case DIS_FIELDTYPE_UINT32:
735             offset = parseField_UInt(tvb, tree, offset,
736                 parserNodes[fieldIndex], 4);
737             break;
738         case DIS_FIELDTYPE_UINT64:
739             offset = parseField_UInt(tvb, tree, offset,
740                 parserNodes[fieldIndex], 8);
741             break;
742         case DIS_FIELDTYPE_FLOAT32:
743             offset = parseField_Float(tvb, tree, offset,
744                 parserNodes[fieldIndex]);
745             break;
746         case DIS_FIELDTYPE_FLOAT64:
747             offset = parseField_Double(tvb, tree, offset,
748                 parserNodes[fieldIndex]);
749             break;
750         case DIS_FIELDTYPE_EXERCISE_ID:
751             pi = proto_tree_add_item(tree, hf_dis_exercise_id, tvb, offset, 1, FALSE);
752             offset += 1;
753             break;
754         case DIS_FIELDTYPE_NUM_ARTICULATION_PARAMS:
755             uintVal = tvb_get_guint8(tvb, offset);
756             pi = proto_tree_add_item(tree, hf_dis_num_art_params, tvb, offset, 1, FALSE);
757             offset += 1;
758             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
759             break;
760         case DIS_FIELDTYPE_PDU_LENGTH:
761             uintVal = tvb_get_ntohs(tvb, offset);
762             pi = proto_tree_add_item(tree, hf_dis_pdu_length, tvb, offset, 2, FALSE);
763             offset += 2;
764             break;
765         case DIS_FIELDTYPE_SITE:
766             uintVal = tvb_get_ntohs(tvb, offset);
767             pi = proto_tree_add_item(tree, hf_dis_entity_id_site, tvb, offset, 2, FALSE);
768             offset += 2;
769             break;
770         case DIS_FIELDTYPE_APPLICATION:
771             uintVal = tvb_get_ntohs(tvb, offset);
772             pi = proto_tree_add_item(tree, hf_dis_entity_id_application, tvb, offset, 2, FALSE);
773             offset += 2;
774             break;
775         case DIS_FIELDTYPE_ENTITY:
776             uintVal = tvb_get_ntohs(tvb, offset);
777             pi = proto_tree_add_item(tree, hf_dis_entity_id_entity, tvb, offset, 2, FALSE);
778             offset += 2;
779             break;
780         case DIS_FIELDTYPE_RADIO_ID:
781             uintVal = tvb_get_ntohs(tvb, offset);
782             pi = proto_tree_add_item(tree, hf_dis_radio_id, tvb, offset, 2, FALSE);
783             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
784             offset += 2;
785             break;
786         case DIS_FIELDTYPE_ENCODING_SCHEME:
787             uintVal = tvb_get_ntohs(tvb, offset);
788             pi = proto_tree_add_item(tree, hf_dis_ens, tvb, offset, 2, FALSE);
789             sub_tree = proto_item_add_subtree(pi, ett_dis_ens);
790             proto_tree_add_item(sub_tree, hf_dis_ens_class, tvb, offset, 2, FALSE);
791             proto_tree_add_item(sub_tree, hf_dis_ens_type, tvb, offset, 2, FALSE);
792             proto_item_set_end(pi, tvb, offset);
793             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
794             offset += 2;
795             break;
796         case DIS_FIELDTYPE_TDL_TYPE:
797             proto_tree_add_item(tree, hf_dis_tdl_type, tvb, offset, 2, FALSE);
798             offset += 2;
799             break;
800         case DIS_FIELDTYPE_SAMPLE_RATE:
801             proto_tree_add_item(tree, hf_dis_sample_rate, tvb, offset, 4, FALSE);
802             offset += 4;
803             break;
804         case DIS_FIELDTYPE_DATA_LENGTH:
805             proto_tree_add_item(tree, hf_dis_data_length, tvb, offset, 2, FALSE);
806             offset += 2;
807             break;
808         case DIS_FIELDTYPE_NUMBER_OF_SAMPLES:
809             uintVal = tvb_get_ntohs(tvb, offset);
810             proto_tree_add_item(tree, hf_dis_num_of_samples, tvb, offset, 2, FALSE);
811             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
812             offset += 2;
813             break;
814
815         case DIS_FIELDTYPE_RADIO_DATA:
816             newtvb = tvb_new_subset(tvb, offset,
817                                     tvb_length_remaining(tvb, offset),
818                                     tvb_reported_length_remaining(tvb, offset)
819                 );
820             proto_tree_add_item(tree, hf_dis_signal_data, newtvb, 0, -1, FALSE );
821             /* ****ck******* need to look for padding bytes */
822             break;
823         case DIS_FIELDTYPE_RADIO_CATEGORY:
824             proto_tree_add_item(tree, hf_dis_radio_category, tvb, offset, 1, FALSE);
825             offset += 1;
826             break;
827         case DIS_FIELDTYPE_NOMENCLATURE_VERSION:
828             proto_tree_add_item(tree, hf_dis_nomenclature_version, tvb, offset, 1, FALSE);
829             offset += 1;
830             break;
831         case DIS_FIELDTYPE_NOMENCLATURE:
832             proto_tree_add_item(tree, hf_dis_nomenclature, tvb, offset, 2, FALSE);
833             offset += 2;
834             break;
835         case DIS_FIELDTYPE_RADIO_TRANSMIT_STATE:
836             uintVal = tvb_get_guint8(tvb, offset);
837             proto_tree_add_item(tree, hf_dis_radio_transmit_state, tvb, offset, 1, FALSE);
838             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
839             offset += 1;
840             break;
841         case DIS_FIELDTYPE_RADIO_INPUT_SOURCE:
842             proto_tree_add_item(tree, hf_dis_radio_input_source, tvb, offset, 1, FALSE);
843             offset += 1;
844             break;
845         case  DIS_FIELDTYPE_ANTENNA_PATTERN_TYPE:
846             uintVal = tvb_get_ntohs(tvb, offset);
847             proto_tree_add_item(tree, hf_dis_antenna_pattern_type, tvb, offset, 2, FALSE);
848             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
849             offset += 2;
850             break;
851         case DIS_FIELDTYPE_ANTENNA_PATTERN_LENGTH:
852             proto_tree_add_item(tree, hf_dis_antenna_pattern_length, tvb, offset, 2, FALSE);
853             offset += 2;
854             break;
855          case DIS_FIELDTYPE_TRANSMIT_FREQUENCY:
856             proto_tree_add_item(tree, hf_dis_transmit_frequency, tvb, offset, 8, FALSE);
857             offset += 8;
858             break;
859         case  DIS_FIELDTYPE_SPREAD_SPECTRUM:
860             spread_spectrum = tvb_get_ntohs(tvb, offset);
861             proto_tree_add_boolean(tree, hf_dis_spread_spectrum_usage, tvb, offset,  2, spread_spectrum);
862             proto_tree_add_boolean(tree, hf_dis_frequency_hopping, tvb, offset,  2, spread_spectrum);
863             proto_tree_add_boolean(tree, hf_dis_pseudo_noise_modulation, tvb, offset,  2, spread_spectrum);
864             proto_tree_add_boolean(tree, hf_dis_time_hopping, tvb, offset,  2, spread_spectrum);
865             offset += 2;
866             break;
867         case DIS_FIELDTYPE_MODULATION_MAJOR:
868             uintVal = tvb_get_ntohs(tvb, offset);
869             proto_tree_add_item(tree, hf_dis_modulation_major, tvb, offset, 2, FALSE);
870             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
871             offset += 2;
872             break;
873         case DIS_FIELDTYPE_MODULATION_SYSTEM:
874             uintVal = tvb_get_ntohs(tvb, offset);
875             proto_tree_add_item(tree, hf_dis_modulation_system, tvb, offset, 2, FALSE);
876             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
877             offset += 2;
878             break;
879         case DIS_FIELDTYPE_CRYPTO_SYSTEM:
880             proto_tree_add_item(tree, hf_dis_crypto_system, tvb, offset, 2, FALSE);
881             offset += 2;
882             break;
883         case DIS_FIELDTYPE_CRYPTO_KEY_ID:
884             pi = proto_tree_add_item(tree, hf_dis_crypto_key, tvb, offset, 2, FALSE);
885             sub_tree = proto_item_add_subtree(pi, ett_dis_crypto_key);
886             proto_tree_add_item(sub_tree, hf_dis_encryption_mode, tvb, offset, 2, FALSE);
887             proto_tree_add_item(sub_tree, hf_dis_key_identifier, tvb, offset, 2, FALSE);
888             proto_item_set_end(pi, tvb, offset);
889             offset += 2;
890             break;
891         case DIS_FIELDTYPE_MODULATION_PARAMETER_LENGTH:
892             uintVal = tvb_get_guint8(tvb, offset);
893             proto_tree_add_item(tree, hf_dis_modulation_parameter_length, tvb, offset, 1, FALSE);
894             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
895             offset += 1;
896             break;
897         case DIS_FIELDTYPE_FH_NETWORK_ID:
898             proto_tree_add_item(tree, hf_dis_mod_param_fh_net_id, tvb, offset, 2, FALSE);
899             offset += 2;
900             break;
901         case DIS_FIELDTYPE_FH_SET_ID:
902             proto_tree_add_item(tree, hf_dis_mod_param_fh_set_id, tvb, offset, 2, FALSE);
903             offset += 2;
904             break;
905         case DIS_FIELDTYPE_LO_SET_ID:
906             proto_tree_add_item(tree, hf_dis_mod_param_fh_lo_set_id, tvb, offset, 2, FALSE);
907             offset += 2;
908             break;
909         case DIS_FIELDTYPE_FH_MSG_START:
910             proto_tree_add_item(tree, hf_dis_mod_param_fh_msg_start, tvb, offset, 1, FALSE);
911             offset += 1;
912             break;
913         case DIS_FIELDTYPE_RESERVED:
914             proto_tree_add_item(tree, hf_dis_mod_param_fh_reserved, tvb, offset, 1, FALSE);
915             offset += 1;
916             break;
917         case DIS_FIELDTYPE_FH_SYNC_TIME_OFFSET:
918             proto_tree_add_item(tree, hf_dis_mod_param_fh_sync_time_offset, tvb, offset, 4, FALSE);
919             offset += 4;
920             break;
921         case DIS_FIELDTYPE_FH_SECURITY_KEY:
922             proto_tree_add_item(tree, hf_dis_mod_param_fh_security_key, tvb, offset, 2, FALSE);
923             offset += 2;
924             break;
925         case DIS_FIELDTYPE_FH_CLEAR_CHANNEL:
926             proto_tree_add_item(tree, hf_dis_mod_param_fh_clear_channel, tvb, offset, 1, FALSE);
927             offset += 1;
928             break;
929         case DIS_FIELDTYPE_TS_ALLOCATION_MODE:
930             proto_tree_add_item(tree, hf_dis_mod_param_ts_allocation_mode, tvb, offset, 1, FALSE);
931             offset += 1;
932             break;
933         case DIS_FIELDTYPE_TRANSMITTER_PRIMARY_MODE:
934             proto_tree_add_item(tree, hf_dis_mod_param_transmitter_prim_mode, tvb, offset, 1, FALSE);
935             offset += 1;
936             break;
937         case DIS_FIELDTYPE_TRANSMITTER_SECONDARY_MODE:
938             proto_tree_add_item(tree, hf_dis_mod_param_transmitter_second_mode, tvb, offset, 1, FALSE);
939             offset += 1;
940             break;
941         case DIS_FIELDTYPE_JTIDS_SYNC_STATE:
942             proto_tree_add_item(tree, hf_dis_mod_param_sync_state, tvb, offset, 1, FALSE);
943             offset += 1;
944             break;
945         case DIS_FIELDTYPE_NETWORK_SYNC_ID:
946             proto_tree_add_item(tree, hf_dis_mod_param_network_sync_id, tvb, offset, 4, FALSE);
947             offset += 4;
948             break;
949         case DIS_FIELDTYPE_MODULATION_PARAMETERS:
950             /* need to check to see if mod parms length > 0 */
951             /* could get here when there are antenna pattern parameter but no mod params */
952             if (modulationParamLength > 0 ) { /* we do have a mod param */
953                 if (systemModulation == DIS_SYSTEM_MOD_CCTT_SINCGARS)
954                 {
955                     pi = proto_tree_add_text(tree, tvb, offset, -1, "%s",
956                                              parserNodes[fieldIndex].fieldLabel);
957                     sub_tree = proto_item_add_subtree(pi, parserNodes[fieldIndex].ettVar);
958                     offset = parseFields(tvb, sub_tree, offset, DIS_FIELDS_MOD_PARAMS_CCTT_SINCGARS);
959                     proto_item_set_end(pi, tvb, offset);
960                     break;
961                 }
962                 else if (systemModulation == DIS_SYSTEM_MOD_JTIDS_MIDS) {
963                     pi = proto_tree_add_text(tree, tvb, offset, -1, "%s",
964                                              parserNodes[fieldIndex].fieldLabel);
965                     sub_tree = proto_item_add_subtree(pi, parserNodes[fieldIndex].ettVar);
966                     offset = parseFields(tvb, sub_tree, offset, DIS_FIELDS_MOD_PARAMS_JTIDS_MIDS);
967                     proto_item_set_end(pi, tvb, offset);
968                     break;
969                 }
970                 else {  /* just dump what is available */
971                     newtvb = tvb_new_subset(tvb, offset,modulationParamLength, modulationParamLength);
972                     proto_tree_add_item(tree, hf_dis_mod_param_dump, newtvb, 0, -1, FALSE );
973                     offset += modulationParamLength;
974                     break;
975                 }
976             } /* else, leave offset alone, and then check antenna pattern param field */
977             break;
978         case DIS_FIELDTYPE_ANTENNA_PATTERN_PARAMETERS:
979             /* just dump the bytes for now.  Need to do finish */
980             newtvb = tvb_new_subset(tvb, offset,
981                                     tvb_length_remaining(tvb, offset),
982                                     tvb_reported_length_remaining(tvb, offset)
983                 );
984             proto_tree_add_item(tree, hf_dis_antenna_pattern_parameter_dump, newtvb, 0, -1, FALSE );
985             break;
986
987
988         /* padding */
989         case DIS_FIELDTYPE_PAD8:
990             offset = parseField_Pad(tvb, tree, offset,
991                 parserNodes[fieldIndex], 1 * fieldRepeatLen);
992             break;
993         case DIS_FIELDTYPE_PAD16:
994             offset = parseField_Pad(tvb, tree, offset,
995                 parserNodes[fieldIndex], 2 * fieldRepeatLen);
996             break;
997         case DIS_FIELDTYPE_PAD24:
998             offset = parseField_Pad(tvb, tree, offset,
999                 parserNodes[fieldIndex], 3 * fieldRepeatLen);
1000             break;
1001         case DIS_FIELDTYPE_PAD32:
1002             offset = parseField_Pad(tvb, tree, offset,
1003                 parserNodes[fieldIndex], 4 * fieldRepeatLen);
1004             break;
1005
1006         /* enumerations (1-byte) */
1007         case DIS_FIELDTYPE_APPLICATION_GENERAL_STATUS:
1008         case DIS_FIELDTYPE_CATEGORY:
1009         case DIS_FIELDTYPE_CONTROL_ID:
1010         case DIS_FIELDTYPE_DETONATION_RESULT:
1011         case DIS_FIELDTYPE_DOMAIN:
1012         case DIS_FIELDTYPE_ENTITY_KIND:
1013         case DIS_FIELDTYPE_FROZEN_BEHAVIOR:
1014         case DIS_FIELDTYPE_PARAMETER_TYPE_DESIGNATOR:
1015         case DIS_FIELDTYPE_PDU_TYPE:
1016         case DIS_FIELDTYPE_PROTOCOL_FAMILY:
1017         case DIS_FIELDTYPE_PROTOCOL_VERSION:
1018         case DIS_FIELDTYPE_REASON:
1019         case DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE:
1020         case DIS_FIELDTYPE_PERSISTENT_OBJECT_CLASS:
1021         case DIS_FIELDTYPE_PERSISTENT_OBJECT_TYPE:
1022         case DIS_FIELDTYPE_EMISSION_FUNCTION:
1023         case DIS_FIELDTYPE_BEAM_FUNCTION:
1024             offset = parseField_Enum(tvb, tree, offset,
1025                 parserNodes[fieldIndex], 1);
1026             break;
1027
1028         /* enumerations (2-bytes) */
1029         case DIS_FIELDTYPE_ACKNOWLEDGE_FLAG:
1030         case DIS_FIELDTYPE_APPLICATION_STATUS_TYPE:
1031         case DIS_FIELDTYPE_APPLICATION_TYPE:
1032         case DIS_FIELDTYPE_RESPONSE_FLAG:
1033         case DIS_FIELDTYPE_MODULATION_DETAIL:
1034         case DIS_FIELDTYPE_EMITTER_NAME:
1035             offset = parseField_Enum(tvb, tree, offset,
1036                 parserNodes[fieldIndex], 2);
1037             break;
1038
1039         /* enumerations (4-bytes) */
1040         case DIS_FIELDTYPE_ACTION_ID:
1041         case DIS_FIELDTYPE_REQUEST_STATUS:
1042             offset = parseField_Enum(tvb, tree, offset,
1043                 parserNodes[fieldIndex], 4);
1044             break;
1045
1046         /* other atomic types */
1047         case DIS_FIELDTYPE_APPEARANCE:
1048             {
1049                 proto_item *newSubtree;
1050                 newField = proto_tree_add_text(tree, tvb, offset, 4, "%s",
1051                     parserNodes[fieldIndex].fieldLabel);
1052                 newSubtree = proto_item_add_subtree(newField,
1053                     parserNodes[fieldIndex].ettVar);
1054                 offset = parseField_Bitmask(tvb, newSubtree, offset,
1055                     parserNodes[fieldIndex], 4);
1056             }
1057             break;
1058         case DIS_FIELDTYPE_ARTIC_PARAM_TYPE:
1059             offset = parseField_UInt(tvb, tree, offset,
1060                 parserNodes[fieldIndex], 4);
1061             break;
1062         case DIS_FIELDTYPE_CAPABILITIES:
1063             offset = parseField_UInt(tvb, tree, offset,
1064                 parserNodes[fieldIndex], 4);
1065             break;
1066         case DIS_FIELDTYPE_COUNTRY:
1067             offset = parseField_UInt(tvb, tree, offset,
1068                 parserNodes[fieldIndex], 2);
1069             break;
1070         case DIS_FIELDTYPE_DATUM_ID:
1071         case DIS_FIELDTYPE_DATUM_LENGTH:
1072             offset = parseField_UInt(tvb, tree, offset,
1073                 parserNodes[fieldIndex], 4);
1074             break;
1075         case DIS_FIELDTYPE_DEAD_RECKONING_PARAMS:
1076             /* This is really a struct... needs a field parser.
1077              * For now, just skip the 12 bytes.
1078              */
1079             offset = parseField_Bytes(tvb, tree, offset,
1080                 parserNodes[fieldIndex], 40);
1081             break;
1082         case DIS_FIELDTYPE_ENTITY_MARKING:
1083             /* This is really a struct... needs a field parser.
1084              * For now, just skip the 12 bytes.
1085              */
1086             offset = parseField_Bytes(tvb, tree, offset,
1087                 parserNodes[fieldIndex], 12);
1088             break;
1089         case DIS_FIELDTYPE_EXTRA:
1090             offset = parseField_UInt(tvb, tree, offset,
1091                 parserNodes[fieldIndex], 1);
1092             break;
1093         case DIS_FIELDTYPE_FIXED_DATUM_VALUE:
1094             offset = parseField_Bytes(tvb, tree, offset,
1095                 parserNodes[fieldIndex], 4);
1096             break;
1097         case DIS_FIELDTYPE_FIXED_LEN_STR:
1098             offset = parseField_Bytes(tvb, tree, offset,
1099                 parserNodes[fieldIndex],
1100                 parserNodes[fieldIndex].fieldRepeatLen);
1101             break;
1102         case DIS_FIELDTYPE_FORCE_ID:
1103             offset = parseField_UInt(tvb, tree, offset,
1104                 parserNodes[fieldIndex], 1);
1105             break;
1106         case DIS_FIELDTYPE_FUSE:
1107             offset = parseField_UInt(tvb, tree, offset,
1108                 parserNodes[fieldIndex], 2);
1109             break;
1110         case DIS_FIELDTYPE_NUM_FIXED_DATA:
1111         case DIS_FIELDTYPE_NUM_VARIABLE_DATA:
1112             offset = parseField_UInt(tvb, tree, offset,
1113                 parserNodes[fieldIndex], 4);
1114             break;
1115         case DIS_FIELDTYPE_REQUEST_ID:
1116             offset = parseField_UInt(tvb, tree, offset,
1117                 parserNodes[fieldIndex], 4);
1118             break;
1119         case DIS_FIELDTYPE_SPECIFIC:
1120             offset = parseField_UInt(tvb, tree, offset,
1121                 parserNodes[fieldIndex], 1);
1122             break;
1123         case DIS_FIELDTYPE_SUBCATEGORY:
1124             offset = parseField_UInt(tvb, tree, offset,
1125                 parserNodes[fieldIndex], 1);
1126             break;
1127         case DIS_FIELDTYPE_TIME_INTERVAL:
1128             offset = parseField_UInt(tvb, tree, offset,
1129                 parserNodes[fieldIndex], 4);
1130             break;
1131         case DIS_FIELDTYPE_TIMESTAMP:
1132             offset = parseField_Timestamp(tvb, tree, offset,
1133                 parserNodes[fieldIndex]);
1134             break;
1135         case DIS_FIELDTYPE_WARHEAD:
1136             offset = parseField_UInt(tvb, tree, offset,
1137                 parserNodes[fieldIndex], 2);
1138             break;
1139
1140         /* composite types */
1141         case DIS_FIELDTYPE_BURST_DESCRIPTOR:
1142         case DIS_FIELDTYPE_CLOCK_TIME:
1143         case DIS_FIELDTYPE_ENTITY_ID:
1144         case DIS_FIELDTYPE_ENTITY_TYPE:
1145         case DIS_FIELDTYPE_RADIO_ENTITY_TYPE:
1146         case DIS_FIELDTYPE_ANTENNA_LOCATION:
1147         case DIS_FIELDTYPE_REL_ANTENNA_LOCATON:
1148         case DIS_FIELDTYPE_EVENT_ID:
1149         case DIS_FIELDTYPE_LINEAR_VELOCITY:
1150         case DIS_FIELDTYPE_LOCATION_ENTITY:
1151         case DIS_FIELDTYPE_LOCATION_WORLD:
1152         case DIS_FIELDTYPE_ORIENTATION:
1153         case DIS_FIELDTYPE_SIMULATION_ADDRESS:
1154         case DIS_FIELDTYPE_VECTOR_32:
1155         case DIS_FIELDTYPE_VECTOR_64:
1156         case DIS_FIELDTYPE_MODULATION_TYPE:
1157         case DIS_FIELDTYPE_EMITTER_SYSTEM:
1158         case DIS_FIELDTYPE_FUNDAMENTAL_PARAMETER_DATA:
1159             newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1160                 parserNodes[fieldIndex].fieldLabel);
1161             if (parserNodes[fieldIndex].children != 0)
1162             {
1163                 proto_item *newSubtree = proto_item_add_subtree(newField,
1164                     parserNodes[fieldIndex].ettVar);
1165                 offset = parseFields(tvb, newSubtree, offset,
1166                     parserNodes[fieldIndex].children);
1167             }
1168             proto_item_set_end(newField, tvb, offset);
1169             break;
1170         case DIS_FIELDTYPE_VARIABLE_DATUM_VALUE:
1171             {
1172                 guint lengthInBytes;
1173                 lengthInBytes = variableDatumLength / 8;
1174                 if (variableDatumLength % 8 > 0)
1175                 {
1176                     lengthInBytes += (8 - (variableDatumLength % 8));
1177                 }
1178                 offset = parseField_Bytes(tvb, tree, offset,
1179                     parserNodes[fieldIndex], lengthInBytes);
1180             }
1181             break;
1182
1183         /* arrays */
1184         case DIS_FIELDTYPE_FIXED_DATUMS:
1185             {
1186                 guint i;
1187                 if (numFixed > INT32_MAX)
1188                 {
1189                     numFixed = INT32_MAX;
1190                 }
1191
1192                 for (i = 0; i < numFixed; ++i)
1193                 {
1194                     /* is remaining length large enough for another fixed datum (ID & value) */
1195                     length = tvb_length_remaining(tvb, offset);
1196                     if ( length >= 8  )
1197                     {
1198                         proto_item *newSubtree;
1199                         newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1200                                                        parserNodes[fieldIndex].fieldLabel);
1201                         newSubtree = proto_item_add_subtree(newField, ettFixedData);
1202                         offset = parseFields
1203                             (tvb, newSubtree, offset,
1204                              parserNodes[fieldIndex].children);
1205                         proto_item_set_end(newField, tvb, offset);
1206                     }
1207                     else {
1208                         THROW(ReportedBoundsError);
1209                         break;
1210                     }
1211                 }
1212             }
1213             break;
1214         case DIS_FIELDTYPE_FIXED_DATUM_IDS:
1215             if (numFixed > 0)
1216             {
1217                 guint       i;
1218                 proto_item *newSubtree;
1219
1220                 newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1221                     parserNodes[fieldIndex].fieldLabel);
1222                 newSubtree = proto_item_add_subtree(newField, ettFixedData);
1223
1224                 if (numFixed > INT32_MAX)
1225                 {
1226                     numFixed = INT32_MAX;
1227                 }
1228
1229                 for (i = 0; i < numFixed; ++i)
1230                 {
1231                     /* is remaining length large enough for another fixed datum ID (32 bit int) */
1232                     if (tvb_length_remaining(tvb, offset) >= 4  )
1233                     {
1234                        offset = parseFields
1235                            (tvb, newSubtree, offset,
1236                             parserNodes[fieldIndex].children);
1237                     }
1238                     else {
1239                         THROW(ReportedBoundsError);
1240                         break;
1241                     }
1242                 }
1243                 proto_item_set_end(newField, tvb, offset);
1244             }
1245             break;
1246         case DIS_FIELDTYPE_VARIABLE_DATUMS:
1247             {
1248                 guint i;
1249                 if (numVariable > INT32_MAX)
1250                 {
1251                     numVariable = INT32_MAX;
1252                 }
1253
1254                 for (i = 0; i < numVariable; ++i)
1255                 {
1256                     proto_item *newSubtree;
1257                     newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1258                         parserNodes[fieldIndex].fieldLabel);
1259                     newSubtree = proto_item_add_subtree
1260                         (newField, ettVariableData);
1261                     offset = parseFields
1262                         (tvb, newSubtree, offset,
1263                          parserNodes[fieldIndex].children);
1264                     proto_item_set_end(newField, tvb, offset);
1265                 }
1266
1267             }
1268             break;
1269         case DIS_FIELDTYPE_VARIABLE_DATUM_IDS:
1270             if (numVariable > 0)
1271             {
1272                 guint       i;
1273                 proto_item *newSubtree;
1274
1275                 newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1276                     parserNodes[fieldIndex].fieldLabel);
1277                 newSubtree = proto_item_add_subtree(newField, ettVariableData);
1278
1279                 if (numVariable > INT32_MAX)
1280                 {
1281                     numVariable = INT32_MAX;
1282                 }
1283
1284                 for (i = 0; i < numVariable; ++i)
1285                 {
1286                     offset = parseFields
1287                         (tvb, newSubtree, offset,
1288                          parserNodes[fieldIndex].children);
1289                 }
1290                 proto_item_set_end(newField, tvb, offset);
1291             }
1292             break;
1293         case DIS_FIELDTYPE_VARIABLE_PARAMETERS:
1294             {
1295                 guint i;
1296
1297                 if (numVariable > DIS_PDU_MAX_VARIABLE_PARAMETERS)
1298                 {
1299                     numVariable = DIS_PDU_MAX_VARIABLE_PARAMETERS;
1300                 }
1301
1302                 for (i = 0; i < numVariable; ++i)
1303                 {
1304                     proto_item *newSubtree;
1305                     newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1306                         parserNodes[fieldIndex].fieldLabel);
1307                     newSubtree = proto_item_add_subtree(newField,
1308                         ettVariableParameters[i]);
1309                     offset = parseFields
1310                         (tvb, newSubtree, offset,
1311                          parserNodes[fieldIndex].children);
1312                     offset = parseField_VariableParameter
1313                         (tvb, newSubtree, offset);
1314                     proto_item_set_end(newField, tvb, offset);
1315                 }
1316             }
1317             break;
1318         case DIS_FIELDTYPE_VARIABLE_RECORDS:
1319             {
1320                 guint i;
1321
1322                 if (numVariable > DIS_PDU_MAX_VARIABLE_RECORDS)
1323                 {
1324                     numVariable = DIS_PDU_MAX_VARIABLE_RECORDS;
1325                 }
1326
1327                 for (i = 0; i < numVariable; ++i)
1328                 {
1329                     /* simple check to detect malformed, field parsers will detect specifics */
1330                     length = tvb_length_remaining(tvb, offset);
1331                     if ( length > 0  )
1332                     {
1333                         proto_item *newSubtree;
1334                         newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1335                                                        parserNodes[fieldIndex].fieldLabel);
1336                         newSubtree = proto_item_add_subtree(newField,
1337                                                             ettVariableRecords[i]);
1338                         offset = parseFields
1339                             (tvb, newSubtree, offset,
1340                              parserNodes[fieldIndex].children);
1341                         offset = parseField_VariableRecord
1342                             (tvb, newSubtree, offset);
1343                         proto_item_set_end(newField, tvb, offset);
1344                     }
1345                     else {
1346                         THROW(ReportedBoundsError);
1347                         break;
1348                     }
1349                 }
1350             }
1351             break;
1352         case DIS_FIELDTYPE_ELECTROMAGNETIC_EMISSION_SYSTEM_BEAM:
1353             {
1354                 guint i;
1355
1356                 for (i = 0; i < numBeams; ++i)
1357                 {
1358                     newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1359                         parserNodes[fieldIndex].fieldLabel);
1360                     if (parserNodes[fieldIndex].children != 0)
1361                     {
1362                         proto_item *newSubtree =
1363                             proto_item_add_subtree(newField,
1364                             parserNodes[fieldIndex].ettVar);
1365                         offset = parseFields(tvb, newSubtree, offset,
1366                             parserNodes[fieldIndex].children);
1367                     }
1368                     proto_item_set_end(newField, tvb, offset);
1369                 }
1370             }
1371             break;
1372         case DIS_FIELDTYPE_TRACK_JAM:
1373             {
1374                 guint i;
1375
1376                 for (i = 0; i < numTrackJamTargets; ++i)
1377                 {
1378                     newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1379                         parserNodes[fieldIndex].fieldLabel);
1380                     if (parserNodes[fieldIndex].children != 0)
1381                     {
1382                         proto_item *newSubtree =
1383                             proto_item_add_subtree(newField,
1384                             parserNodes[fieldIndex].ettVar);
1385                         offset = parseFields(tvb, newSubtree, offset,
1386                             parserNodes[fieldIndex].children);
1387                     }
1388                     proto_item_set_end(newField, tvb, offset);
1389                 }
1390             }
1391             break;
1392         case DIS_FIELDTYPE_NUM_ELECTROMAGNETIC_EMISSION_SYSTEMS:
1393             uintVal = tvb_get_guint8(tvb, offset);
1394             pi = proto_tree_add_item(tree, hf_dis_num_electromagnetic_emission_systems, tvb, offset, 1, FALSE);
1395             offset += 1;
1396             *(parserNodes[fieldIndex].outputVar) = (guint32)uintVal;
1397             break;
1398         case DIS_FIELDTYPE_ELECTROMAGNETIC_EMISSION_SYSTEM:
1399             {
1400                 guint i;
1401
1402                 if (numVariable > DIS_PDU_MAX_ELECTROMAGNETIC_EMISSION_SYSTEMS)
1403                 {
1404                     numVariable = DIS_PDU_MAX_ELECTROMAGNETIC_EMISSION_SYSTEMS;
1405                 }
1406
1407                 for (i = 0; i < numVariable; ++i)
1408                 {
1409                     newField = proto_tree_add_text(tree, tvb, offset, -1, "%s",
1410                         parserNodes[fieldIndex].fieldLabel);
1411                     if (parserNodes[fieldIndex].children != 0)
1412                     {
1413                         proto_item *newSubtree =
1414                             proto_item_add_subtree(newField,
1415                             parserNodes[fieldIndex].ettVar);
1416                         offset = parseFields(tvb, newSubtree, offset,
1417                             parserNodes[fieldIndex].children);
1418                     }
1419                     proto_item_set_end(newField, tvb, offset);
1420                 }
1421             }
1422             break;
1423         default:
1424             break;
1425         }
1426
1427         ++fieldIndex;
1428         length = tvb_length_remaining(tvb, offset);
1429     }
1430
1431     return offset;
1432 }