aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-dis-pdus.c
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2005-07-11 22:23:15 +0000
committerAnders Broman <anders.broman@ericsson.com>2005-07-11 22:23:15 +0000
commita063532343ff5e5f7d4795471ef2b29eaae9e43d (patch)
tree5939f89af9f4cfb3f31a494f853e89819e60c70a /epan/dissectors/packet-dis-pdus.c
parenteba6c1a70fdbf900255e5a0c45c90b7d98c443cf (diff)
From Jeremy j Ouellette:
DIS dissection. svn path=/trunk/; revision=14899
Diffstat (limited to 'epan/dissectors/packet-dis-pdus.c')
-rw-r--r--epan/dissectors/packet-dis-pdus.c401
1 files changed, 401 insertions, 0 deletions
diff --git a/epan/dissectors/packet-dis-pdus.c b/epan/dissectors/packet-dis-pdus.c
new file mode 100644
index 0000000000..fb66a8b8d1
--- /dev/null
+++ b/epan/dissectors/packet-dis-pdus.c
@@ -0,0 +1,401 @@
+/* packet-dis-pdus.c
+ * Routines and definitions for DIS PDU parsing.
+ * Copyright 2005, Scientific Research Corporation
+ * Initial implementation by Jeremy Ouellette <jouellet@scires.com>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#include "packet-dis-pdus.h"
+#include "packet-dis-fields.h"
+
+guint32 numArticulations;
+gint ettArticulations[DIS_PDU_MAX_ARTICULATIONS];
+
+DIS_ParserNode DIS_PARSER_ENTITY_STATE_PDU[] =
+{
+ { DIS_FIELDTYPE_ENTITY_ID, "Entity ID",0,0,0 },
+ { DIS_FIELDTYPE_FORCE_ID, "Force ID",0,0,0 },
+ { DIS_FIELDTYPE_UINT8, "Number of Articulation Parameters",0,0,&numArticulations },
+ { DIS_FIELDTYPE_ENTITY_TYPE, "Entity Type",0,0,0 },
+ { DIS_FIELDTYPE_ENTITY_TYPE, "Alternative Entity Type",0,0,0 },
+ { DIS_FIELDTYPE_LINEAR_VELOCITY, "Entity Linear Velocity",0,0,0 },
+ { DIS_FIELDTYPE_LOCATION_WORLD, "Entity Location",0,0,0 },
+ { DIS_FIELDTYPE_ORIENTATION, "Entity Orientation",0,0,0 },
+ { DIS_FIELDTYPE_APPEARANCE, "Entity Appearance",0,0,0 },
+ { DIS_FIELDTYPE_DEAD_RECKONING_PARAMS, "Dead Reckoning Parameters",0,0,0 },
+ { DIS_FIELDTYPE_ENTITY_MARKING, "Entity Marking",0,0,0 },
+ { DIS_FIELDTYPE_CAPABILITIES, "Capabilities",0,0,0 },
+ { DIS_FIELDTYPE_ARTICULATION_PARAMETERS, "Articulation Parameters",0,0,0 },
+ { DIS_FIELDTYPE_END, NULL,0,0,0 }
+};
+
+DIS_ParserNode DIS_PARSER_FIRE_PDU[] =
+{
+ { DIS_FIELDTYPE_ENTITY_ID, "Firing Entity ID",0,0,0 },
+ { DIS_FIELDTYPE_ENTITY_ID, "Target Entity ID",0,0,0 },
+ { DIS_FIELDTYPE_ENTITY_ID, "Munition ID",0,0,0 },
+ { DIS_FIELDTYPE_EVENT_ID, "Event ID",0,0,0 },
+ { DIS_FIELDTYPE_UINT32, "Fire Mission Index",0,0,0 },
+ { DIS_FIELDTYPE_LOCATION_WORLD, "Location in World Coordinates",0,0,0 },
+ { DIS_FIELDTYPE_BURST_DESCRIPTOR, "Burst Descriptor",0,0,0 },
+ { DIS_FIELDTYPE_LINEAR_VELOCITY, "Velocity",0,0,0 },
+ { DIS_FIELDTYPE_FLOAT32, "Range",0,0,0 },
+ { DIS_FIELDTYPE_END, NULL,0,0,0 }
+};
+
+DIS_ParserNode DIS_PARSER_DETONATION_PDU[] =
+{
+ { DIS_FIELDTYPE_ENTITY_ID, "Firing Entity ID",0,0,0 },
+ { DIS_FIELDTYPE_ENTITY_ID, "Target Entity ID",0,0,0 },
+ { DIS_FIELDTYPE_ENTITY_ID, "Munition ID",0,0,0 },
+ { DIS_FIELDTYPE_EVENT_ID, "Event ID",0,0,0 },
+ { DIS_FIELDTYPE_LINEAR_VELOCITY, "Velocity",0,0,0 },
+ { DIS_FIELDTYPE_LOCATION_WORLD, "Location in World Coordinates",0,0,0 },
+ { DIS_FIELDTYPE_BURST_DESCRIPTOR, "Burst Descriptor",0,0,0 },
+ { DIS_FIELDTYPE_LOCATION_ENTITY, "Location in Entity Coordinates",0,0,0 },
+ { DIS_FIELDTYPE_DETONATION_RESULT, "Detonation Result",0,0,0 },
+ { DIS_FIELDTYPE_UINT8, "Number of Articulation Parameters",0,0,0 },
+ { DIS_FIELDTYPE_PAD16, "Padding",0,0,0 },
+ { DIS_FIELDTYPE_ARTICULATION_PARAMETERS, "Articulation Parameters",0,0,0 },
+ { DIS_FIELDTYPE_END, NULL,0,0,0 }
+};
+
+/* Initialize the parsers for each PDU type and the standard DIS header.
+ */
+void initializeParsers(void)
+{
+ initializeParser(DIS_PARSER_ENTITY_STATE_PDU);
+ initializeParser(DIS_PARSER_FIRE_PDU);
+ initializeParser(DIS_PARSER_DETONATION_PDU);
+ initializeParser(DIS_FIELDS_PDU_HEADER);
+}
+
+/* Create a specific subtree for a PDU or a composite PDU field.
+ */
+DIS_ParserNode *createSubtree(DIS_ParserNode parserNodes[], gint *ettVar)
+{
+ guint fieldIndex = 0;
+ guint fieldCount;
+ gint *ett[1];
+ DIS_ParserNode *newSubtree;
+
+ while (parserNodes[fieldIndex].fieldType != DIS_FIELDTYPE_END)
+ {
+ ++fieldIndex;
+ }
+
+ fieldCount = fieldIndex + 1;
+
+ newSubtree = (DIS_ParserNode*)g_malloc(sizeof(DIS_ParserNode) * fieldCount);
+
+ memcpy(newSubtree, parserNodes, sizeof(DIS_ParserNode) * fieldCount);
+
+ initializeParser(newSubtree);
+
+ ett[0] = ettVar;
+ proto_register_subtree_array(ett, array_length(ett));
+
+ return newSubtree;
+}
+
+/* Initialize an array of parser nodes.
+ */
+void initializeParser(DIS_ParserNode parserNodes[])
+{
+ guint parserIndex = 0;
+
+ /* Create the parser subtrees for each of the composite field types.
+ */
+ while (parserNodes[parserIndex].fieldType != DIS_FIELDTYPE_END)
+ {
+ switch (parserNodes[parserIndex].fieldType)
+ {
+ case DIS_FIELDTYPE_APPEARANCE:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_NONE,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_ARTICULATION_PARAMETERS:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_ARTICULATION_PARAMETER,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_BURST_DESCRIPTOR:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_BURST_DESCRIPTOR,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_ENTITY_ID:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_ENTITY_ID,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_ENTITY_TYPE:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_ENTITY_TYPE,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_EVENT_ID:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_EVENT_ID,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_LINEAR_VELOCITY:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_LINEAR_VELOCITY,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_LOCATION_WORLD:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_LOCATION_WORLD,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_LOCATION_ENTITY:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_LOCATION_ENTITY,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ case DIS_FIELDTYPE_ORIENTATION:
+ parserNodes[parserIndex].children = createSubtree(
+ DIS_FIELDS_ORIENTATION,
+ &parserNodes[parserIndex].ettVar);
+ break;
+ default:
+ break;
+ }
+ ++parserIndex;
+ }
+}
+
+/* Parse packet data based on a specified array of DIS_ParserNodes.
+ */
+gint parseFields(tvbuff_t *tvb, proto_tree *tree, gint offset, DIS_ParserNode parserNodes[])
+{
+ guint fieldIndex = 0;
+
+ while (parserNodes[fieldIndex].fieldType != DIS_FIELDTYPE_END)
+ {
+ proto_item *newField = 0;
+ switch(parserNodes[fieldIndex].fieldType)
+ {
+ case DIS_FIELDTYPE_INT8:
+ offset = parseField_Int(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_INT16:
+ offset = parseField_Int(tvb, tree, offset,
+ parserNodes[fieldIndex], 2);
+ break;
+ case DIS_FIELDTYPE_INT32:
+ offset = parseField_Int(tvb, tree, offset,
+ parserNodes[fieldIndex], 4);
+ break;
+ case DIS_FIELDTYPE_INT64:
+ offset = parseField_Int(tvb, tree, offset,
+ parserNodes[fieldIndex], 8);
+ break;
+ case DIS_FIELDTYPE_UINT8:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_UINT16:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 2);
+ break;
+ case DIS_FIELDTYPE_UINT32:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 4);
+ break;
+ case DIS_FIELDTYPE_UINT64:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 8);
+ break;
+ case DIS_FIELDTYPE_FLOAT32:
+ offset = parseField_Float(tvb, tree, offset,
+ parserNodes[fieldIndex]);
+ break;
+ case DIS_FIELDTYPE_FLOAT64:
+ offset = parseField_Double(tvb, tree, offset,
+ parserNodes[fieldIndex]);
+ break;
+ case DIS_FIELDTYPE_PAD8:
+ offset = parseField_Pad(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_PAD16:
+ offset = parseField_Pad(tvb, tree, offset,
+ parserNodes[fieldIndex], 2);
+ break;
+ case DIS_FIELDTYPE_PAD32:
+ offset = parseField_Pad(tvb, tree, offset,
+ parserNodes[fieldIndex], 4);
+ break;
+ case DIS_FIELDTYPE_APPEARANCE:
+ {
+ proto_item *newSubtree;
+ newField = proto_tree_add_text(tree, tvb, offset, 4,
+ parserNodes[fieldIndex].fieldLabel);
+ newSubtree = proto_item_add_subtree(newField,
+ parserNodes[fieldIndex].ettVar);
+ offset = parseField_Bitmask(tvb, newSubtree, offset,
+ parserNodes[fieldIndex], 4);
+ }
+ break;
+ case DIS_FIELDTYPE_ARTIC_PARAM_TYPE_DESIGNATOR:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_ARTIC_PARAM_TYPE:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 4);
+ break;
+ case DIS_FIELDTYPE_CAPABILITIES:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 4);
+ break;
+ case DIS_FIELDTYPE_CATEGORY:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_COUNTRY:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 2);
+ break;
+ case DIS_FIELDTYPE_DEAD_RECKONING_PARAMS:
+ /* This is really a struct... needs a field parser.
+ * For now, just skip the 12 bytes.
+ */
+ offset = parseField_Bytes(tvb, tree, offset,
+ parserNodes[fieldIndex], 40);
+ break;
+ case DIS_FIELDTYPE_DETONATION_RESULT:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_DOMAIN:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_ENTITY_KIND:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_ENTITY_MARKING:
+ /* This is really a struct... needs a field parser.
+ * For now, just skip the 12 bytes.
+ */
+ offset = parseField_Bytes(tvb, tree, offset,
+ parserNodes[fieldIndex], 12);
+ break;
+ case DIS_FIELDTYPE_EXTRA:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_FORCE_ID:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_FUSE:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 2);
+ break;
+ case DIS_FIELDTYPE_PDU_TYPE:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_PROTOCOL_FAMILY:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_PROTOCOL_VERSION:
+ offset = parseField_Enum(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_SPECIFIC:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_SUBCATEGORY:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 1);
+ break;
+ case DIS_FIELDTYPE_TIMESTAMP:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 4);
+ break;
+ case DIS_FIELDTYPE_WARHEAD:
+ offset = parseField_UInt(tvb, tree, offset,
+ parserNodes[fieldIndex], 2);
+ break;
+ case DIS_FIELDTYPE_BURST_DESCRIPTOR:
+ case DIS_FIELDTYPE_ENTITY_ID:
+ case DIS_FIELDTYPE_EVENT_ID:
+ case DIS_FIELDTYPE_LINEAR_VELOCITY:
+ case DIS_FIELDTYPE_LOCATION_WORLD:
+ case DIS_FIELDTYPE_LOCATION_ENTITY:
+ case DIS_FIELDTYPE_ENTITY_TYPE:
+ case DIS_FIELDTYPE_ORIENTATION:
+ newField = proto_tree_add_text(tree, tvb, offset, -1,
+ parserNodes[fieldIndex].fieldLabel);
+ if (parserNodes[fieldIndex].children != 0)
+ {
+ proto_item *newSubtree = proto_item_add_subtree(newField,
+ parserNodes[fieldIndex].ettVar);
+ offset = parseFields(tvb, newSubtree, offset,
+ parserNodes[fieldIndex].children);
+ }
+ proto_item_set_end(newField, tvb, offset);
+ break;
+ case DIS_FIELDTYPE_ARTICULATION_PARAMETERS:
+ {
+ guint i;
+
+ if (numArticulations > DIS_PDU_MAX_ARTICULATIONS)
+ {
+ numArticulations = DIS_PDU_MAX_ARTICULATIONS;
+ }
+
+ for (i = 0; i < numArticulations; ++i)
+ {
+ proto_item *newSubtree;
+ newField = proto_tree_add_text(tree, tvb, offset, -1,
+ parserNodes[fieldIndex].fieldLabel);
+ newSubtree = proto_item_add_subtree(newField,
+ ettArticulations[i]);
+ offset = parseFields(tvb, newSubtree, offset,
+ parserNodes[fieldIndex].children);
+ proto_item_set_end(newField, tvb, offset);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ ++fieldIndex;
+ }
+
+ return offset;
+}