2 * Routines and definitions for DIS field parsing.
3 * Copyright 2005, Scientific Research Corporation
4 * Initial implementation by Jeremy Ouellette <jouellet@scires.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
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.
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.
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.
31 #include <epan/packet.h>
32 #include "packet-dis-fields.h"
33 #include "packet-dis-enums.h"
34 #include "packet-dis-pdus.h"
36 /* all of these variables are assigned by reference */
37 /* *(parserNode.outputVar) = value */
38 guint32 disProtocolVersion;
40 guint32 protocolFamily;
41 guint32 persistentObjectPduType;
45 guint32 disRadioTransmitState;
46 guint32 encodingScheme;
50 guint32 variableDatumLength;
51 guint32 variableParameterType;
52 guint32 variableRecordLength;
53 guint32 variableRecordType;
54 guint32 majorModulation;
55 guint32 systemModulation;
56 guint32 modulationParamLength;
57 guint32 disAntennaPattern;
61 DIS_ParserNode DIS_FIELDS_PDU_HEADER[] =
63 { DIS_FIELDTYPE_PROTOCOL_VERSION, "Protocol Version",0,0,0,&disProtocolVersion },
64 { DIS_FIELDTYPE_EXERCISE_ID, "Exercise ID",0,0,0,0 },
65 { DIS_FIELDTYPE_PDU_TYPE, "PDU Type",0,0,0,&pduType },
66 { DIS_FIELDTYPE_PROTOCOL_FAMILY, "Protocol Family",0,0,0,&protocolFamily },
67 { DIS_FIELDTYPE_TIMESTAMP, "Timestamp",0,0,0,0 },
68 { DIS_FIELDTYPE_PDU_LENGTH, "Length",0,0,0,0 },
69 { DIS_FIELDTYPE_PAD16, "Padding",0,0,0,0 },
70 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
73 DIS_ParserNode DIS_FIELDS_PERSISTENT_OBJECT_HEADER[] =
75 { DIS_FIELDTYPE_UINT8, "Protocol Version",0,0,0,0 },
76 { DIS_FIELDTYPE_PERSISTENT_OBJECT_TYPE, "PO PDU Type",0,0,0,&persistentObjectPduType },
77 { DIS_FIELDTYPE_UINT8, "Exercise ID",0,0,0,0 },
78 { DIS_FIELDTYPE_UINT8, "PO Database ID",0,0,0,0 },
79 { DIS_FIELDTYPE_UINT16, "Length",0,0,0,0 },
80 { DIS_FIELDTYPE_UINT16, "PDU Count",0,0,0,0 },
81 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
87 DIS_ParserNode DIS_FIELDS_BURST_DESCRIPTOR[] =
89 { DIS_FIELDTYPE_ENTITY_TYPE, "Munition",0,0,0,0 },
90 { DIS_FIELDTYPE_WARHEAD, "Warhead",0,0,0,0 },
91 { DIS_FIELDTYPE_FUSE, "Fuse",0,0,0,0 },
92 { DIS_FIELDTYPE_UINT16, "Quantity",0,0,0,0 },
93 { DIS_FIELDTYPE_UINT16, "Rate",0,0,0,0 },
94 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
97 DIS_ParserNode DIS_FIELDS_CLOCK_TIME[] =
99 { DIS_FIELDTYPE_UINT32, "Hour",0,0,0,0 },
100 { DIS_FIELDTYPE_TIMESTAMP, "Time Past The Hour",0,0,0,0 },
101 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
104 DIS_ParserNode DIS_FIELDS_ENTITY_ID[] =
106 { DIS_FIELDTYPE_SITE, "Site",0,0,0,0 },
107 { DIS_FIELDTYPE_APPLICATION, "Application",0,0,0,0 },
108 { DIS_FIELDTYPE_ENTITY, "Entity",0,0,0,0 },
109 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
112 DIS_ParserNode DIS_FIELDS_ENTITY_TYPE[] =
114 { DIS_FIELDTYPE_ENTITY_KIND, "Entity Kind",0,0,0,&entityKind },
115 { DIS_FIELDTYPE_DOMAIN, "Domain",0,0,0,&entityDomain },
116 { DIS_FIELDTYPE_COUNTRY, "Country",0,0,0,0 },
117 { DIS_FIELDTYPE_CATEGORY, "Category",0,0,0,0 },
118 { DIS_FIELDTYPE_SUBCATEGORY, "Subcategory",0,0,0,0 },
119 { DIS_FIELDTYPE_SPECIFIC, "Specific",0,0,0,0 },
120 { DIS_FIELDTYPE_EXTRA, "Extra",0,0,0,0 },
121 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
124 DIS_ParserNode DIS_FIELDS_RADIO_ENTITY_TYPE[] =
126 { DIS_FIELDTYPE_ENTITY_KIND, "Entity Kind",0,0,0,&entityKind },
127 { DIS_FIELDTYPE_DOMAIN, "Domain",0,0,0,&entityDomain },
128 { DIS_FIELDTYPE_COUNTRY, "Country",0,0,0,0 },
129 { DIS_FIELDTYPE_RADIO_CATEGORY, "Radio Category",0,0,0,0 },
130 { DIS_FIELDTYPE_NOMENCLATURE_VERSION, "Nomenclature Version",0,0,0,0 },
131 { DIS_FIELDTYPE_NOMENCLATURE, "Nomenclature",0,0,0,0 },
132 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
135 DIS_ParserNode DIS_FIELDS_MODULATION_TYPE[] =
137 { DIS_FIELDTYPE_SPREAD_SPECTRUM, "Spread Spectrum",0,0,0,0 },
138 { DIS_FIELDTYPE_MODULATION_MAJOR, "Major",0,0,0,&majorModulation },
139 { DIS_FIELDTYPE_MODULATION_DETAIL, "Detail",0,0,0,0 },
140 { DIS_FIELDTYPE_MODULATION_SYSTEM, "System",0,0,0,&systemModulation },
141 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
144 DIS_ParserNode DIS_FIELDS_EVENT_ID[] =
146 { DIS_FIELDTYPE_UINT16, "Site",0,0,0,0 },
147 { DIS_FIELDTYPE_UINT16, "Application",0,0,0,0 },
148 { DIS_FIELDTYPE_UINT16, "Event Number",0,0,0,0 },
149 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
152 DIS_ParserNode DIS_FIELDS_ORIENTATION[] =
154 { DIS_FIELDTYPE_FLOAT32, "Psi",0,0,0,0 },
155 { DIS_FIELDTYPE_FLOAT32, "Theta",0,0,0,0 },
156 { DIS_FIELDTYPE_FLOAT32, "Phi",0,0,0,0 },
157 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
160 DIS_ParserNode DIS_FIELDS_SIMULATION_ADDRESS[] =
162 { DIS_FIELDTYPE_UINT16, "Site",0,0,0,0 },
163 { DIS_FIELDTYPE_UINT16, "Application",0,0,0,0 },
164 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
167 DIS_ParserNode DIS_FIELDS_VECTOR_FLOAT_32[] =
169 { DIS_FIELDTYPE_FLOAT32, "X",0,0,0,0 },
170 { DIS_FIELDTYPE_FLOAT32, "Y",0,0,0,0 },
171 { DIS_FIELDTYPE_FLOAT32, "Z",0,0,0,0 },
172 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
175 DIS_ParserNode DIS_FIELDS_VECTOR_FLOAT_64[] =
177 { DIS_FIELDTYPE_FLOAT64, "X",0,0,0,0 },
178 { DIS_FIELDTYPE_FLOAT64, "Y",0,0,0,0 },
179 { DIS_FIELDTYPE_FLOAT64, "Z",0,0,0,0 },
180 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
183 DIS_ParserNode DIS_FIELDS_MOD_PARAMS_CCTT_SINCGARS[] =
185 { DIS_FIELDTYPE_FH_NETWORK_ID, "Frequency Hopping Network ID",0,0,0,0 },
186 { DIS_FIELDTYPE_FH_SET_ID, "Frequency Set ID",0,0,0,0 },
187 { DIS_FIELDTYPE_LO_SET_ID, "Lockout Set ID",0,0,0,0 },
188 { DIS_FIELDTYPE_FH_MSG_START, "Frequency Hopping Message Start",0,0,0,0 },
189 { DIS_FIELDTYPE_RESERVED, "Reserved",0,0,0,0 },
190 { DIS_FIELDTYPE_FH_SYNC_TIME_OFFSET, "FH Synchronization Time Offset",0,0,0,0 },
191 { DIS_FIELDTYPE_FH_SECURITY_KEY, "Transmission Security Key",0,0,0,0 },
192 { DIS_FIELDTYPE_FH_CLEAR_CHANNEL, "Clear Channel",0,0,0,0 },
193 { DIS_FIELDTYPE_PAD8, "Padding",0,0,0,0 },
194 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
197 DIS_ParserNode DIS_FIELDS_MOD_PARAMS_JTIDS_MIDS[] =
199 { DIS_FIELDTYPE_TS_ALLOCATION_MODE, "Time Slot Allocaton Mode",0,0,0,0 },
200 { DIS_FIELDTYPE_TRANSMITTER_PRIMARY_MODE, "Transmitter Primary Mode",0,0,0,0 },
201 { DIS_FIELDTYPE_TRANSMITTER_SECONDARY_MODE, "Transmitter Secondary Mode",0,0,0,0 },
202 { DIS_FIELDTYPE_JTIDS_SYNC_STATE, "Synchronization State",0,0,0,0 },
203 { DIS_FIELDTYPE_NETWORK_SYNC_ID, "Network Sync ID",0,0,0,0 },
204 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
209 DIS_ParserNode DIS_FIELDS_FIXED_DATUM[] =
211 { DIS_FIELDTYPE_DATUM_ID, "Datum ID",0,0,0,0 },
212 { DIS_FIELDTYPE_FIXED_DATUM_VALUE, "Datum value",0,0,0,0 },
213 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
216 DIS_ParserNode DIS_FIELDS_VARIABLE_DATUM[] =
218 { DIS_FIELDTYPE_DATUM_ID, "Datum ID",0,0,0,0 },
219 { DIS_FIELDTYPE_DATUM_LENGTH, "Datum length",0,0,0,&variableDatumLength },
220 { DIS_FIELDTYPE_VARIABLE_DATUM_VALUE, "Datum value",0,0,0,0 },
221 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
224 DIS_ParserNode DIS_FIELDS_DATUM_IDS[] =
226 { DIS_FIELDTYPE_DATUM_ID, "Datum ID",0,0,0,0 },
227 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
230 /* Variable Parameters
232 DIS_ParserNode DIS_FIELDS_VP_TYPE[] =
234 { DIS_FIELDTYPE_PARAMETER_TYPE_DESIGNATOR, "Variable Parameter Type",0,0,0,&variableParameterType },
235 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
238 /* Array record contents - variable parameter records
240 DIS_ParserNode DIS_FIELDS_VP_GENERIC[] =
242 { DIS_FIELDTYPE_FIXED_LEN_STR, "Data",15,0,0,0 },
243 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
246 DIS_ParserNode DIS_FIELDS_VP_ARTICULATED_PART[] =
248 { DIS_FIELDTYPE_UINT8, "Change",0,0,0,0 },
249 { DIS_FIELDTYPE_UINT16, "Part Attached To ID",0,0,0,0 },
250 { DIS_FIELDTYPE_ARTIC_PARAM_TYPE, "Parameter Type",0,0,0,0 },
251 { DIS_FIELDTYPE_UINT64, "Parameter Value",0,0,0,0 },
252 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
255 DIS_ParserNode DIS_FIELDS_VP_ATTACHED_PART[] =
257 { DIS_FIELDTYPE_UINT8, "Attached Indicator",0,0,0,0 },
258 { DIS_FIELDTYPE_UINT16, "Part Attached To ID",0,0,0,0 },
259 { DIS_FIELDTYPE_ARTIC_PARAM_TYPE, "Parameter Type",0,0,0,0 },
260 { DIS_FIELDTYPE_ENTITY_TYPE, "Part Type",0,0,0,0 },
261 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
264 DIS_ParserNode DIS_FIELDS_VP_ENTITY_OFFSET[] =
266 { DIS_FIELDTYPE_UINT8, "Offset Type",0,0,0,0 },
267 { DIS_FIELDTYPE_PAD8, "Padding",2,0,0,0 },
268 { DIS_FIELDTYPE_VECTOR_32, "Offset",0,0,0,0 },
269 { DIS_FIELDTYPE_ORIENTATION, "Orientation",0,0,0,0 },
270 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
275 DIS_ParserNode DIS_FIELDS_VR_TYPE[] =
277 { DIS_FIELDTYPE_UINT32, "Record Type",0,0,0,&variableRecordType },
278 { DIS_FIELDTYPE_UINT16, "Record Length",0,0,0,&variableRecordLength },
279 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
282 DIS_ParserNode DIS_FIELDS_VR_APPLICATION_HEALTH_STATUS[] =
284 { DIS_FIELDTYPE_PAD8, "Padding",2,0,0,0 },
285 { DIS_FIELDTYPE_APPLICATION_STATUS_TYPE, "Status Type",0,0,0,0 },
286 { DIS_FIELDTYPE_APPLICATION_GENERAL_STATUS, "General Status",0,0,0,0 },
287 { DIS_FIELDTYPE_UINT8, "Specific Status",0,0,0,0 },
288 { DIS_FIELDTYPE_INT32, "Status Value Int",0,0,0,0 },
289 { DIS_FIELDTYPE_FLOAT64, "Status Value Float",0,0,0,0 },
290 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
293 DIS_ParserNode DIS_FIELDS_VR_APPLICATION_INITIALIZATION[] =
295 { DIS_FIELDTYPE_UINT8, "Exercise ID",0,0,0,0 },
296 { DIS_FIELDTYPE_PAD8, "Padding",0,0,0,0 },
297 { DIS_FIELDTYPE_FIXED_LEN_STR, "Exercise File Path",256,0,0,0 },
298 { DIS_FIELDTYPE_FIXED_LEN_STR, "Exercise File Name",128,0,0,0 },
299 { DIS_FIELDTYPE_FIXED_LEN_STR, "Application Role",64,0,0,0 },
300 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
303 DIS_ParserNode DIS_FIELDS_VR_DATA_QUERY[] =
305 { DIS_FIELDTYPE_UINT16, "Num Records",0,0,0,&numFixed },
306 { DIS_FIELDTYPE_FIXED_DATUM_IDS, "Record",0,0,0,0 },
307 { DIS_FIELDTYPE_END, NULL,0,0,0,0 }
312 DIS_ParserNode DIS_FIELDS_NONE[] =
314 { DIS_FIELDTYPE_END, NULL, 0,0,0,0 }
317 DIS_BitMask DIS_APPEARANCE_LANDPLATFORM[] =
319 { 0x00000001, 0, "Paint Scheme", {
320 { 0, "Uniform color" },
324 { 0x00000002, 1, "Mobility", {
325 { 0, "No mobility kill" },
326 { 1, "Mobility kill" },
329 { 0x00000004, 2, "Fire Power", {
330 { 0, "No fire-power kill" },
331 { 1, "Fire-power kill" },
334 { 0x00000018, 3, "Damage", {
336 { 1, "Slight damage" },
337 { 2, "Moderate damage" },
346 DIS_BitMask DIS_APPEARANCE_LIFEFORM[] =
348 { 0x00000001, 0, "Paint Scheme", {
349 { 0, "Uniform color" },
353 { 0x00000018, 3, "Health", {
355 { 1, "Slight injury" },
356 { 2, "Moderate injury" },
357 { 3, "Fatal injury" },
365 /* Initialize the field parsers that are not explicitly included in any
366 * specific PDU. These fields are only accessed and used if a variant
367 * field indicates they are to be used.
369 void initializeFieldParsers()
371 initializeParser(DIS_FIELDS_VP_GENERIC);
372 initializeParser(DIS_FIELDS_VP_ARTICULATED_PART);
373 initializeParser(DIS_FIELDS_VP_ATTACHED_PART);
374 initializeParser(DIS_FIELDS_VP_ENTITY_OFFSET);
376 initializeParser(DIS_FIELDS_VR_APPLICATION_HEALTH_STATUS);
377 initializeParser(DIS_FIELDS_VR_APPLICATION_INITIALIZATION);
378 initializeParser(DIS_FIELDS_VR_DATA_QUERY);
379 initializeParser(DIS_FIELDS_MOD_PARAMS_CCTT_SINCGARS);
380 initializeParser(DIS_FIELDS_MOD_PARAMS_JTIDS_MIDS);
384 /* Adjust an offset variable for proper alignment for a specified field length.
386 static gint alignOffset(gint offset, guint fieldLength)
388 gint remainder = offset % fieldLength;
391 offset += fieldLength - remainder;
396 /* Parse a field consisting of a specified number of bytes. This field parser
397 * doesn't perform any alignment.
399 gint parseField_Bytes(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode, guint numBytes)
401 proto_tree_add_text(tree, tvb, offset, numBytes, "%s (%d bytes)",
402 parserNode.fieldLabel, numBytes);
407 /* Parse a bitmask field.
409 gint parseField_Bitmask(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode, guint numBytes)
411 DIS_BitMask *bitMask = 0;
414 offset = alignOffset(offset, numBytes);
419 uintVal = tvb_get_guint8(tvb, offset);
422 uintVal = tvb_get_ntohs(tvb, offset);
425 uintVal = tvb_get_ntohl(tvb, offset);
428 uintVal = tvb_get_ntoh64(tvb, offset);
435 switch(parserNode.fieldType)
437 case DIS_FIELDTYPE_APPEARANCE:
438 if ((entityKind == DIS_ENTITYKIND_PLATFORM) &&
439 (entityDomain == DIS_DOMAIN_LAND))
441 bitMask = DIS_APPEARANCE_LANDPLATFORM;
443 else if (entityKind == DIS_ENTITYKIND_LIFE_FORM)
445 bitMask = DIS_APPEARANCE_LIFEFORM;
455 while (bitMask[maskIndex].maskBits != 0)
458 DIS_BitMaskMapping *bitMaskMap = bitMask[maskIndex].bitMappings;
460 while (bitMaskMap[mapIndex].label != 0)
462 if (((bitMask[maskIndex].maskBits & uintVal) >> bitMask[maskIndex].shiftBits) ==
463 bitMaskMap[mapIndex].value)
465 proto_tree_add_text(tree, tvb, offset, numBytes,
466 "%s = %s", bitMask[maskIndex].label,
467 bitMaskMap[mapIndex].label);
477 proto_tree_add_text(tree, tvb, offset, numBytes,
478 "Unknown Appearance Type (%" G_GINT64_MODIFIER "u)", uintVal);
486 /* Parse an unsigned integer field of a specified number of bytes.
488 gint parseField_UInt(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode, guint numBytes)
492 offset = alignOffset(offset, numBytes);
497 uintVal = tvb_get_guint8(tvb, offset);
500 uintVal = tvb_get_ntohs(tvb, offset);
503 uintVal = tvb_get_ntohl(tvb, offset);
506 uintVal = tvb_get_ntoh64(tvb, offset);
513 proto_tree_add_text(tree, tvb, offset, numBytes, "%s = %" G_GINT64_MODIFIER "u",
514 parserNode.fieldLabel, uintVal);
516 if (parserNode.outputVar != 0)
518 *(parserNode.outputVar) = (guint32)uintVal;
526 /* Parse a signed integer field of a specified number of bytes.
528 gint parseField_Int(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode, guint numBytes)
532 offset = alignOffset(offset, numBytes);
537 uintVal = tvb_get_guint8(tvb, offset);
540 uintVal = tvb_get_ntohs(tvb, offset);
543 uintVal = tvb_get_ntohl(tvb, offset);
546 uintVal = tvb_get_ntoh64(tvb, offset);
553 proto_tree_add_text(tree, tvb, offset, numBytes, "%s = %" G_GINT64_MODIFIER "d",
554 parserNode.fieldLabel, uintVal);
561 /* Parse a field that explicitly specified a number of pad bytes (vs implicit
562 * padding, which occurs whenever padding is inserted to properly align the
565 gint parseField_Pad(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode _U_, guint numBytes)
567 proto_tree_add_text(tree, tvb, offset, numBytes,
568 "Explicit Padding (%d bytes)", numBytes);
575 /* Parse an enumerated type field.
577 gint parseField_Enum(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode, guint numBytes)
579 const value_string *enumStrings = 0;
581 const gchar *enumStr = 0;
582 proto_item *pi = NULL;
585 offset = alignOffset(offset, numBytes);
587 switch(parserNode.fieldType)
589 case DIS_FIELDTYPE_ACKNOWLEDGE_FLAG:
590 enumStrings = DIS_PDU_AcknowledgeFlag_Strings;
592 case DIS_FIELDTYPE_ACTION_ID:
593 enumStrings = DIS_PDU_ActionId_Strings;
595 case DIS_FIELDTYPE_APPLICATION_GENERAL_STATUS:
596 enumStrings = DIS_PDU_ApplicationGeneralStatus_Strings;
598 case DIS_FIELDTYPE_APPLICATION_STATUS_TYPE:
599 enumStrings = DIS_PDU_ApplicationStatusType_Strings;
601 case DIS_FIELDTYPE_APPLICATION_TYPE:
602 enumStrings = DIS_PDU_ApplicationType_Strings;
604 case DIS_FIELDTYPE_CONTROL_ID:
605 enumStrings = DIS_PDU_ControlId_Strings;
607 case DIS_FIELDTYPE_PROTOCOL_VERSION:
608 enumStrings = DIS_PDU_ProtocolVersion_Strings;
609 dis_hf_id = hf_dis_proto_ver;
611 case DIS_FIELDTYPE_PROTOCOL_FAMILY:
612 enumStrings = DIS_PDU_ProtocolFamily_Strings;
613 dis_hf_id = hf_dis_proto_fam;
615 case DIS_FIELDTYPE_PDU_TYPE:
616 enumStrings = DIS_PDU_Type_Strings;
617 dis_hf_id = hf_dis_pdu_type;
619 case DIS_FIELDTYPE_ENTITY_KIND:
620 enumStrings = DIS_PDU_EntityKind_Strings;
622 case DIS_FIELDTYPE_DOMAIN:
623 enumStrings = DIS_PDU_Domain_Strings;
625 case DIS_FIELDTYPE_DETONATION_RESULT:
626 enumStrings = DIS_PDU_DetonationResult_Strings;
628 case DIS_FIELDTYPE_FROZEN_BEHAVIOR:
629 enumStrings = DIS_PDU_FrozenBehavior_Strings;
631 case DIS_FIELDTYPE_RADIO_CATEGORY:
632 enumStrings = DIS_PDU_RadioCategory_Strings;
634 case DIS_FIELDTYPE_NOMENCLATURE_VERSION:
635 enumStrings = DIS_PDU_NomenclatureVersion_Strings;
637 case DIS_FIELDTYPE_NOMENCLATURE:
638 enumStrings = DIS_PDU_Nomenclature_Strings;
640 case DIS_FIELDTYPE_CATEGORY:
641 if (entityKind == DIS_ENTITYKIND_PLATFORM)
645 case DIS_DOMAIN_LAND:
646 enumStrings = DIS_PDU_Category_LandPlatform_Strings;
649 enumStrings = DIS_PDU_Category_AirPlatform_Strings;
651 case DIS_DOMAIN_SURFACE:
652 enumStrings = DIS_PDU_Category_SurfacePlatform_Strings;
654 case DIS_DOMAIN_SUBSURFACE:
655 enumStrings = DIS_PDU_Category_SubsurfacePlatform_Strings;
657 case DIS_DOMAIN_SPACE:
658 enumStrings = DIS_PDU_Category_SpacePlatform_Strings;
666 case DIS_FIELDTYPE_PARAMETER_TYPE_DESIGNATOR:
667 enumStrings = DIS_PDU_ParameterTypeDesignator_Strings;
669 case DIS_FIELDTYPE_PERSISTENT_OBJECT_TYPE:
670 enumStrings = DIS_PDU_PersistentObjectType_Strings;
672 case DIS_FIELDTYPE_PERSISTENT_OBJECT_CLASS:
673 enumStrings = DIS_PDU_PO_ObjectClass_Strings;
675 case DIS_FIELDTYPE_REASON:
676 enumStrings = DIS_PDU_Reason_Strings;
678 case DIS_FIELDTYPE_REQUEST_STATUS:
679 enumStrings = DIS_PDU_RequestStatus_Strings;
681 case DIS_FIELDTYPE_REQUIRED_RELIABILITY_SERVICE:
682 enumStrings = DIS_PDU_RequiredReliabilityService_Strings;
684 case DIS_FIELDTYPE_RESPONSE_FLAG:
685 enumStrings = DIS_PDU_DisResponseFlag_Strings;
687 case DIS_FIELDTYPE_MODULATION_DETAIL:
688 switch (majorModulation) {
689 case DIS_MAJOR_MOD_AMPLITUDE:
690 enumStrings = DIS_PDU_DetailModulationAmplitude_Strings;
692 case DIS_MAJOR_MOD_AMPLITUDE_AND_ANGLE:
693 enumStrings = DIS_PDU_DetailModulationAmpAndAngle_Strings;
695 case DIS_MAJOR_MOD_ANGLE:
696 enumStrings = DIS_PDU_DetailModulationAngle_Strings;
698 case DIS_MAJOR_MOD_COMBINATION:
699 enumStrings = DIS_PDU_DetailModulationCombination_Strings;
701 case DIS_MAJOR_MOD_PULSE:
702 enumStrings = DIS_PDU_DetailModulationPulse_Strings;
704 case DIS_MAJOR_MOD_UNMODULATED:
705 enumStrings = DIS_PDU_DetailModulationUnmodulated_Strings;
707 case DIS_MAJOR_MOD_CPSM: /* CPSM only has "other" defined */
708 case DIS_MAJOR_MOD_OTHER:
710 enumStrings = DIS_PDU_DetailModulationCPSM_Strings;
722 enumVal = tvb_get_guint8(tvb, offset);
725 enumVal = tvb_get_ntohs(tvb, offset);
728 enumVal = tvb_get_ntohl(tvb, offset);
735 if (enumStrings != 0)
737 enumStr = val_to_str(enumVal, enumStrings, "Unknown Enum Value (%d)");
741 enumStr = "Unknown Enum Type";
744 if (dis_hf_id != -1) {
745 pi = proto_tree_add_item(tree, dis_hf_id, tvb, offset, 1, FALSE);
746 /* proto_item_set_text(pi, "%s = %s", parserNode.fieldLabel, enumStr); */
749 proto_tree_add_text(tree, tvb, offset, numBytes, "%s = %s",
750 parserNode.fieldLabel, enumStr);
752 if (parserNode.outputVar != 0)
754 *(parserNode.outputVar) = enumVal;
762 /* Parse a 4-byte floating-point value.
764 gint parseField_Float(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode)
768 offset = alignOffset(offset, 4);
769 floatVal = tvb_get_ntohieee_float(tvb, offset);
770 proto_tree_add_text(tree, tvb, offset, 4, "%s = %f",
771 parserNode.fieldLabel, floatVal);
778 /* Parse a 4-byte floating-point value, given text label.
780 gint parseField_Float_Text(tvbuff_t *tvb, proto_tree *tree, gint offset, gchar *charStr)
784 offset = alignOffset(offset, 4);
785 floatVal = tvb_get_ntohieee_float(tvb, offset);
786 proto_tree_add_text(tree, tvb, offset, 4, "%s = %f",
794 /* Parse an 8-byte floating-point value.
796 gint parseField_Double(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode)
800 offset = alignOffset(offset, 8);
801 doubleVal = tvb_get_ntohieee_double(tvb, offset);
802 proto_tree_add_text(tree, tvb, offset, 8, "%s = %f",
803 parserNode.fieldLabel, doubleVal);
810 /* Parse the Timestamp */
811 gint parseField_Timestamp(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNode)
814 static double MSEC_PER_SECOND = 1000.0;
815 static double MSEC_PER_MINUTE = 60.0 * 1000.0 ;
816 static double MSEC_PER_HOUR = 60.0 * 60.0 * 1000.0;
817 static double FSV = 0x7fffffff;
819 guint isAbsolute = 0;
826 offset = alignOffset(offset, 4);
828 /* convert to host value */
829 uintVal = tvb_get_ntohl(tvb, offset);
830 /* determine absolute vis sim time */
834 /* convert TS to MS */
835 ms = (uintVal >> 1) * MSEC_PER_HOUR / FSV;
838 /* calc minutes and reduce ms */
839 minutes = (guint) (ms / MSEC_PER_MINUTE);
840 ms -= (minutes * MSEC_PER_MINUTE);
842 /* calc seconds and reduce ms */
843 seconds = (guint) (ms / MSEC_PER_SECOND);
844 ms -= (seconds * MSEC_PER_SECOND);
846 /* truncate milliseconds */
847 milliseconds = (guint) ms;
849 /* push out the values */
852 proto_tree_add_text(tree, tvb, offset, 4, "%s = %02d:%02d %03d absolute (UTM)",
853 parserNode.fieldLabel, minutes, seconds, milliseconds);
857 proto_tree_add_text(tree, tvb, offset, 4, "%s = %02d:%02d %03d relative",
858 parserNode.fieldLabel, minutes, seconds, milliseconds);
865 /* Parse a variable parameter field.
867 gint parseField_VariableParameter(tvbuff_t *tvb, proto_tree *tree, gint offset)
869 DIS_ParserNode *paramParser = 0;
871 /* Determine the parser to use based on the type */
872 switch (variableParameterType) {
873 case DIS_PARAM_TYPE_DESIG_ARTICULATED_PART:
874 paramParser = DIS_FIELDS_VP_ARTICULATED_PART;
876 case DIS_PARAM_TYPE_DESIG_ATTACHED_PART:
877 paramParser = DIS_FIELDS_VP_ATTACHED_PART;
879 case DIS_PARAM_TYPE_DESIG_ENTITY_OFFSET:
880 paramParser = DIS_FIELDS_VP_ENTITY_OFFSET;
883 paramParser = DIS_FIELDS_VP_GENERIC;
887 /* Parse the variable parameter fields */
890 offset = parseFields(tvb, tree, offset, paramParser);
896 /* Parse a variable record field.
898 gint parseField_VariableRecord(tvbuff_t *tvb, proto_tree *tree, gint offset)
900 DIS_ParserNode *paramParser = 0;
902 /* Determine the parser to use based on the type */
903 switch (variableRecordType) {
905 paramParser = DIS_FIELDS_VR_APPLICATION_HEALTH_STATUS;
908 paramParser = DIS_FIELDS_VR_APPLICATION_INITIALIZATION;
911 paramParser = DIS_FIELDS_VR_DATA_QUERY;
915 guint32 dataLength = variableRecordLength - 6;
919 proto_tree_add_text(tree, tvb, offset, dataLength,
920 "Record Data (%d bytes)", dataLength);
921 offset += dataLength;
927 /* Parse the variable record fields */
930 offset = parseFields(tvb, tree, offset, paramParser);
933 /* Should alignment padding be added */
934 if (variableRecordLength % 8)
936 guint32 alignmentPadding = (8 - (variableRecordLength % 8));
938 proto_tree_add_text(tree, tvb, offset, alignmentPadding,
939 "Alignment Padding (%d bytes)", alignmentPadding);
940 offset += alignmentPadding;