wireshark/epan/dissectors/packet-stanag4607.c

1648 lines
48 KiB
C

/* packet-stanag4607.c
* Routines for STANAG 4607 dissection
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <math.h>
#include <epan/packet.h>
#include <epan/expert.h>
#include <wiretap/stanag4607.h>
void proto_register_stanag4607(void);
void proto_reg_handoff_stanag4607(void);
static int proto_stanag4607 = -1;
static int hf_4607_version = -1;
static int hf_4607_packet_size = -1;
static int hf_4607_nationality = -1;
static int hf_4607_sec_class = -1;
static int hf_4607_sec_system = -1;
static int hf_4607_sec_code = -1;
static int hf_4607_exercise_indicator = -1;
static int hf_4607_platform_id = -1;
static int hf_4607_mission_id = -1;
static int hf_4607_job_id = -1;
static int hf_4607_segment_type = -1;
static int hf_4607_segment_size = -1;
/* Mission Segment */
static int hf_4607_mission_plan = -1;
static int hf_4607_mission_flight_plan = -1;
static int hf_4607_mission_platform = -1;
static int hf_4607_mission_platform_config = -1;
static int hf_4607_mission_time_year = -1;
static int hf_4607_mission_time_month = -1;
static int hf_4607_mission_time_day = -1;
/* Dwell Segment */
static int hf_4607_dwell_mask = -1;
static int hf_4607_dwell_revisit_index = -1;
static int hf_4607_dwell_dwell_index = -1;
static int hf_4607_dwell_last_dwell = -1;
static int hf_4607_dwell_count = -1;
static int hf_4607_dwell_time = -1;
static int hf_4607_dwell_sensor_lat = -1;
static int hf_4607_dwell_sensor_lon = -1;
static int hf_4607_dwell_sensor_alt = -1;
static int hf_4607_dwell_scale_lat = -1;
static int hf_4607_dwell_scale_lon = -1;
static int hf_4607_dwell_unc_along = -1;
static int hf_4607_dwell_unc_cross = -1;
static int hf_4607_dwell_unc_alt = -1;
static int hf_4607_dwell_track = -1;
static int hf_4607_dwell_speed = -1;
static int hf_4607_dwell_vert_velocity = -1;
static int hf_4607_dwell_track_unc = -1;
static int hf_4607_dwell_speed_unc = -1;
static int hf_4607_dwell_vv_unc = -1;
static int hf_4607_dwell_plat_heading = -1;
static int hf_4607_dwell_plat_pitch = -1;
static int hf_4607_dwell_plat_roll = -1;
static int hf_4607_dwell_da_lat = -1;
static int hf_4607_dwell_da_lon = -1;
static int hf_4607_dwell_da_range = -1;
static int hf_4607_dwell_da_angle = -1;
static int hf_4607_dwell_sensor_heading = -1;
static int hf_4607_dwell_sensor_pitch = -1;
static int hf_4607_dwell_sensor_roll = -1;
static int hf_4607_dwell_mdv = -1;
/* Target Report */
static int hf_4607_dwell_report_index = -1;
static int hf_4607_dwell_report_lat = -1;
static int hf_4607_dwell_report_lon = -1;
static int hf_4607_dwell_report_delta_lat = -1;
static int hf_4607_dwell_report_delta_lon = -1;
static int hf_4607_dwell_report_height = -1;
static int hf_4607_dwell_report_radial = -1;
static int hf_4607_dwell_report_wrap = -1;
static int hf_4607_dwell_report_snr = -1;
static int hf_4607_dwell_report_class = -1;
static int hf_4607_dwell_report_prob = -1;
static int hf_4607_dwell_report_unc_slant = -1;
static int hf_4607_dwell_report_unc_cross = -1;
static int hf_4607_dwell_report_unc_height = -1;
static int hf_4607_dwell_report_unc_radial = -1;
static int hf_4607_dwell_report_tag_app = -1;
static int hf_4607_dwell_report_tag_entity = -1;
static int hf_4607_dwell_report_section = -1;
/* Job Definition Segment */
static int hf_4607_jobdef_job_id = -1;
static int hf_4607_jobdef_sensor_type = -1;
static int hf_4607_jobdef_sensor_model = -1;
static int hf_4607_jobdef_filter = -1;
static int hf_4607_jobdef_priority = -1;
static int hf_4607_jobdef_ba_lat_a = -1;
static int hf_4607_jobdef_ba_lon_a = -1;
static int hf_4607_jobdef_ba_lat_b = -1;
static int hf_4607_jobdef_ba_lon_b = -1;
static int hf_4607_jobdef_ba_lat_c = -1;
static int hf_4607_jobdef_ba_lon_c = -1;
static int hf_4607_jobdef_ba_lat_d = -1;
static int hf_4607_jobdef_ba_lon_d = -1;
static int hf_4607_jobdef_radar_mode = -1;
static int hf_4607_jobdef_revisit_interval = -1;
static int hf_4607_jobdef_unc_along = -1;
static int hf_4607_jobdef_unc_cross = -1;
static int hf_4607_jobdef_unc_alt = -1;
static int hf_4607_jobdef_unc_heading = -1;
static int hf_4607_jobdef_unc_speed = -1;
static int hf_4607_jobdef_sense_slant = -1;
static int hf_4607_jobdef_sense_cross = -1;
static int hf_4607_jobdef_sense_vlos = -1;
static int hf_4607_jobdef_sense_mdv = -1;
static int hf_4607_jobdef_sense_prob = -1;
static int hf_4607_jobdef_sense_alarm = -1;
static int hf_4607_jobdef_terrain_model = -1;
static int hf_4607_jobdef_geoid_model = -1;
/* Platform Location Segment */
static int hf_4607_platloc_time = -1;
static int hf_4607_platloc_latitude = -1;
static int hf_4607_platloc_longitude = -1;
static int hf_4607_platloc_altitude = -1;
static int hf_4607_platloc_track = -1;
static int hf_4607_platloc_speed = -1;
static int hf_4607_platloc_vertical_velocity = -1;
/* Subtree pointers */
static gint ett_4607_hdr = -1;
static gint ett_4607_seg = -1;
static gint ett_4607_rpt = -1;
/* Error pointers */
static expert_field ei_bad_length = EI_INIT;
static expert_field ei_too_short = EI_INIT;
static expert_field ei_bad_packet_size = EI_INIT;
static dissector_handle_t stanag4607_handle;
static const value_string stanag4607_class_vals[] = {
{ 1, "TOP SECRET" },
{ 2, "SECRET" },
{ 3, "CONFIDENTIAL" },
{ 4, "RESTRICTED" },
{ 5, "UNCLASSIFIED" },
{ 0, NULL }
};
static const value_string stanag4607_exind_vals[] = {
{ 0, "Operation, Real Data" },
{ 1, "Operation, Simulated Data" },
{ 2, "Operation, Synthesized Data" },
{ 128, "Exercise, Real Data" },
{ 129, "Exercise, Simulated Data" },
{ 130, "Exercise, Synthesized Data" },
{ 0, NULL }
};
#define MISSION_SEGMENT 1
#define DWELL_SEGMENT 2
#define JOB_DEFINITION_SEGMENT 5
#define PLATFORM_LOCATION_SEGMENT 13
static const value_string stanag4607_segment_vals[] = {
{ 1, "Mission Segment" },
{ 2, "Dwell Segment" },
{ 3, "HRR Segment" },
{ 5, "Job Definition Segment" },
{ 6, "Free Text Segment" },
{ 7, "Low Reflectivity Index Segment" },
{ 8, "Group Segment" },
{ 9, "Attached Target Segment" },
{ 10, "Test and Status Segment" },
{ 11, "System-Specific Segment" },
{ 12, "Processing History Segment" },
{ 13, "Platform Location Segment" },
{ 101, "Job Request Segment" },
{ 102, "Job Acknowledgment Segment" },
{ 0, NULL }
};
static const value_string stanag4607_sensor_vals[] = {
{ 0, "Unidentified" },
{ 1, "Other" },
{ 2, "HiSAR" },
{ 3, "ASTOR" },
{ 4, "Rotary Wing Radar" },
{ 5, "Global Hawk Sensor" },
{ 6, "HORIZON" },
{ 7, "APY-3" },
{ 8, "APY-6" },
{ 9, "APY-8 (Lynx I)" },
{ 10, "RADARSAT2" },
{ 11, "ASARS-2A" },
{ 12, "TESAR" },
{ 13, "MP-RTIP" },
{ 14, "APG-77" },
{ 15, "APG-79" },
{ 16, "APG-81" },
{ 17, "APY-6v1" },
{ 18, "SPY-I (Lynx II)" },
{ 19, "SIDM" },
{ 20, "LIMIT" },
{ 21, "TCAR (AGS A321)" },
{ 22, "LSRS Sensor" },
{ 23, "UGS Single Sensor" },
{ 24, "UGS Cluster Sensor" },
{ 25, "IMASTER GMTI" },
{ 26, "AN/ZPY-1 (STARLite)" },
{ 27, "VADER" },
{ 255, "No Statement" },
{ 0, NULL }
};
static const value_string stanag4607_radar_mode_vals[] = {
{ 0, "Unspecified Mode" },
{ 1, "MTI (Moving Target Indicator)" },
{ 2, "HRR (High Range Resolution)" },
{ 3, "UHRR (Ultra High Range Resolution)" },
{ 4, "HUR (High Update Rate)" },
{ 5, "FTI" },
/* TODO: and many many more ... */
{ 0, NULL }
};
static const value_string stanag4607_terrain_vals[] = {
{ 0, "None Specified" },
{ 1, "DTED0 (Digital Terrain Elevation Data, Level 0)" },
{ 2, "DTED1 (Digital Terrain Elevation Data, Level 1)" },
{ 3, "DTED2 (Digital Terrain Elevation Data, Level 2)" },
{ 4, "DTED3 (Digital Terrain Elevation Data, Level 3)" },
{ 5, "DTED4 (Digital Terrain Elevation Data, Level 4)" },
{ 6, "DTED5 (Digital Terrain Elevation Data, Level 5)" },
{ 7, "SRTM1 (Shuttle Radar Topography Mission, Level 1)" },
{ 8, "SRTM2 (Shuttle Radar Topography Mission, Level 2)" },
{ 9, "DGM50 M745 (Digitales Gelandemodell 1:50 000)" },
{ 10, "DGM250 (Digitales Gelandemodell 1:250 000)" },
{ 11, "ITHD (Interferometric Terrain Data Height)" },
{ 12, "STHD (Stereometric Terrain Data Height)" },
{ 13, "SEDRIS (SEDRIS Reference Model ISO/IEC 18026)" },
{ 0, NULL }
};
static const value_string stanag4607_geoid_vals[] = {
{ 0, "None Specified" },
{ 1, "EGM96 (Earth Gravitional Model, Version 1996)" },
{ 2, "GEO96 (Geoid Gravitional Model, Version 1996)" },
{ 3, "Flat Earth" },
{ 0, NULL }
};
static const value_string stanag4607_target_vals[] = {
{ 0, "No Information, Live Target" },
{ 1, "Tracked Vehicle, Live Target" },
{ 2, "Wheeled Vehicle, Live Target" },
{ 3, "Rotary Wing Aircraft, Live Target" },
{ 4, "Fixed Wing Aircraft, Live Target" },
{ 5, "Stationary Rotator, Live Target" },
{ 6, "Maritime, Live Target" },
{ 7, "Beacon, Live Target" },
{ 8, "Amphibious, Live Target" },
{ 9, "Person, Live Target" },
{ 10, "Vehicle, Live Target" },
{ 11, "Animal, Live Target" },
{ 12, "Large Multiple-Return, Live Land Target" },
{ 13, "Large Multiple-Return, Live Maritime Target" },
{ 126, "Other, Live Target" },
{ 127, "Unknown, Live Target" },
{ 128, "No Information, Simulated Target" },
{ 129, "Tracked Vehicle, Simulated Target" },
{ 130, "Wheeled Vehicle, Simulated Target" },
{ 131, "Rotary Wing Aircraft, Simulated Target" },
{ 132, "Fixed Wing Aircraft, Simulated Target" },
{ 133, "Stationary Rotator, Simulated Target" },
{ 134, "Maritme, Simulated Target" },
{ 135, "Beacon, Simulated Target" },
{ 136, "Amphibious, Simulated Target" },
{ 137, "Person, Simulated Target" },
{ 138, "Vehicle, Simulated Target" },
{ 139, "Animal, Simulated Target" },
{ 140, "Large Multiple-Return, Simulated Land Target" },
{ 141, "Large Multiple-Return, Simulated Maritime Target" },
{ 143, "Tagging Device" },
{ 254, "Other, Simulated Target" },
{ 255, "Unknown, Simulated Target" },
{ 0, NULL }
};
static const value_string stanag4607_platform_vals[] = {
{ 0, "Unidentified" },
{ 1, "ACS" },
{ 2, "ARL-M" },
{ 3, "Sentinel" },
{ 4, "Rotary Wing Radar" },
{ 5, "Global Hawk-Navy" },
{ 6, "HORIZON" },
{ 7, "E-8 (Joint STARS)" },
{ 8, "P-3C" },
{ 9, "Predator" },
{ 10, "RADARSAT2" },
{ 11, "U-2" },
{ 12, "E-10" },
{ 13, "UGS - Single" },
{ 14, "UGS - Cluster" },
{ 15, "Ground Based" },
{ 16, "UAV-Army" },
{ 17, "UAV-Marines" },
{ 18, "UAV-Navy" },
{ 19, "UAV-Air Force" },
{ 20, "Global Hawk-Air Force" },
{ 21, "Global Hawk-Australia" },
{ 22, "Global Hawk-Germany" },
{ 23, "Paul Revere" },
{ 24, "Mariner UAV" },
{ 25, "BAC-111" },
{ 26, "Coyote" },
{ 27, "King Air" },
{ 28, "LIMIT" },
{ 29, "NRL NP-3B" },
{ 30, "SOSTAR-X" },
{ 31, "WatchKeeper" },
{ 32, "Alliance Ground Surveillance (AGS) (A321)" },
{ 33, "Stryker" },
{ 34, "AGS (HALE UAV)" },
{ 35, "SIDM" },
{ 36, "Reaper" },
{ 37, "Warrior A" },
{ 38, "Warrior" },
{ 39, "Twin Otter" },
{ 255, "Other" },
{ 0, NULL }
};
static void
prt_sa32(gchar *buff, guint32 val)
{
double deg, min, sec;
double x = (double) ((gint32) val);
x /= (double) (1UL<<30);
x *= 45.0;
deg = floor(x);
min = floor(60.0 * (x - deg));
sec = 60.0 * (60.0 * (x - deg) - min);
/* checkAPI.pl doesn't like the unicode degree symbol, I don't know what to do... */
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.8f degrees (%.0f %.0f\' %.2f\")", x, deg, min, sec);
}
static void
prt_ba32(gchar *buff, guint32 val)
{
double deg, min, sec;
double x = (double) val;
x /= (double) (1UL<<30);
x *= 90.0;
deg = floor(x);
min = floor(60.0 * (x - deg));
sec = 60.0 * (60.0 * (x - deg) - min);
/* checkAPI.pl doesn't like the unicode degree symbol, I don't know what to do... */
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.8f degrees (%.0f %.0f\' %.2f\")", x, deg, min, sec);
}
static void
prt_sa16(gchar *buff, guint32 val)
{
double x = (double) ((gint32) val);
x /= (double) (1<<14);
x *= 90.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f degrees", x);
}
static void
prt_ba16(gchar *buff, guint32 val)
{
double x = (double) val;
x /= (double) (1<<14);
x *= 90.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f degrees", x);
}
static void
prt_ba16_none(gchar *buff, guint32 val)
{
double x = (double) val;
x /= (double) (1<<14);
x *= 90.0;
if (val <= 65536)
g_snprintf(buff, ITEM_LABEL_LENGTH, "No Statement");
else
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f degrees", x);
}
static void
prt_kilo(gchar *buff, guint32 val)
{
double x = (double) ((gint32) val);
x /= 128.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.2f kilometers", x);
}
static void
prt_meters(gchar *buff, guint32 val)
{
double x = (double) ((gint32) val);
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.0f meters", x);
}
static void
prt_decimeters(gchar *buff, guint32 val)
{
double x = (double) ((gint32) val);
x /= 10.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.1f meters", x);
}
static void
prt_centimeters(gchar *buff, guint32 val)
{
double x = (double) ((gint32) val);
x /= 100.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.2f meters", x);
}
static void
prt_speed(gchar *buff, guint32 val)
{
double x = (double) val;
x /= 1000.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f meters/second", x);
}
static void
prt_speed_centi(gchar *buff, guint32 val)
{
double x = (double) ((gint32) val);
x /= 100.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.2f meters/second", x);
}
static void
prt_speed_deci(gchar *buff, guint32 val)
{
/* Usually 8-bit, signed */
double x = (double) ((gint32) val);
x /= 10.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.1f meters/second", x);
}
static void
prt_millisec(gchar *buff, guint32 val)
{
double x = (double) val;
x /= 1000.0;
g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f seconds", x);
}
static void
prt_none8(gchar *buff, guint32 val)
{
if (0xff == val)
g_snprintf(buff, ITEM_LABEL_LENGTH, "No Statement");
else
g_snprintf(buff, ITEM_LABEL_LENGTH, "%d", val);
}
static void
prt_none16(gchar *buff, guint32 val)
{
if (0xffff == val)
g_snprintf(buff, ITEM_LABEL_LENGTH, "No Statement");
else
g_snprintf(buff, ITEM_LABEL_LENGTH, "%d", val);
}
static gint
dissect_mission(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
{
proto_tree_add_item(seg_tree, hf_4607_mission_plan, tvb, offset, 12, ENC_ASCII|ENC_NA);
offset += 12;
proto_tree_add_item(seg_tree, hf_4607_mission_flight_plan, tvb, offset, 12, ENC_ASCII|ENC_NA);
offset += 12;
proto_tree_add_item(seg_tree, hf_4607_mission_platform, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_mission_platform_config, tvb, offset, 10, ENC_ASCII|ENC_NA);
offset += 10;
proto_tree_add_item(seg_tree, hf_4607_mission_time_year, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_mission_time_month, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_mission_time_day, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
return offset;
}
/* Dwell Segment Existence Mask */
/* The Dxx fields are NOT bit locations! They are the field numbers
* as specified in Table 2-4 Dwell Segment. These field numbers DO NOT
* count bit locations in the existence mask (even though they come
* close to this). The m and n values of the m*8+n offset below are
* given in Figure 2-1 titled "Dwell Segment Existence Mask Mapping."
*/
#define SET(MASK,OFF) (((MASK)>>(OFF)) & G_GINT64_CONSTANT(1))
#define D10 6*8+7
#define D12 6*8+5
#define D15 6*8+2
#define D18 5*8+7
#define D21 5*8+4
#define D24 5*8+1
#define D28 4*8+5
#define D31 4*8+2
#define D32_1 4*8+1
#define D32_2 4*8+0
#define D32_6 3*8+4
#define D32_7 3*8+3
#define D32_9 3*8+1
#define D32_10 3*8+0
#define D32_11 2*8+7
#define D32_12 2*8+6
#define D32_16 2*8+2
#define D32_18 2*8+0
/* Target Report */
static gint
dissect_target(tvbuff_t *tvb, proto_tree *seg_tree, gint offset, guint64 mask)
{
proto_item *rpt_item = NULL;
proto_tree *rpt_tree = seg_tree;
if (SET(mask, D32_1)) {
rpt_item = proto_tree_add_item(rpt_tree, hf_4607_dwell_report_index, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
rpt_tree = proto_item_add_subtree(rpt_item, ett_4607_rpt);
}
if (SET(mask, D32_2)) {
rpt_item = proto_tree_add_item(rpt_tree, hf_4607_dwell_report_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
} else {
rpt_item = proto_tree_add_item(rpt_tree, hf_4607_dwell_report_delta_lat, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_delta_lon, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
/* If the report index wasn't set, then no subtree yet */
if (rpt_item && rpt_tree == seg_tree) {
rpt_tree = proto_item_add_subtree(rpt_item, ett_4607_rpt);
}
if (SET(mask, D32_6)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_height, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
if (SET(mask, D32_7)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_radial, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_wrap, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
if (SET(mask, D32_9)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_snr, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
if (SET(mask, D32_10)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_class, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
if (SET(mask, D32_11)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_prob, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
if (SET(mask, D32_12)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_slant, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_cross, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_height, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_radial, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
if (SET(mask, D32_16)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_tag_app, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_tag_entity, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
}
if (SET(mask, D32_18)) {
proto_tree_add_item(rpt_tree, hf_4607_dwell_report_section, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
return offset;
}
/* Dwell Segment */
static gint
dissect_dwell(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
{
guint64 mask;
guint32 count;
mask = tvb_get_ntoh64(tvb, offset);
proto_tree_add_item(seg_tree, hf_4607_dwell_mask, tvb, offset, 8, ENC_BIG_ENDIAN);
offset += 8;
proto_tree_add_item(seg_tree, hf_4607_dwell_revisit_index, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_dwell_index, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_last_dwell, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
/* count of target reports */
count = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(seg_tree, hf_4607_dwell_count, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_time, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_alt, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
if (SET(mask, D10)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_scale_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_scale_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
}
if (SET(mask, D12)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_unc_along, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_unc_cross, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_unc_alt, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
if (SET(mask, D15)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_track, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_speed, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_vert_velocity, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
if (SET(mask, D18)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_track_unc, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_dwell_speed_unc, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_vv_unc, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
if (SET(mask, D21)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_plat_heading, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_plat_pitch, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_plat_roll, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
/* Mandatory Dwell Area */
proto_tree_add_item(seg_tree, hf_4607_dwell_da_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_da_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_dwell_da_range, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_da_angle, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
if (SET(mask, D28)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_heading, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_pitch, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_roll, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
}
if (SET(mask, D31)) {
proto_tree_add_item(seg_tree, hf_4607_dwell_mdv, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
}
while (count--) {
offset = dissect_target(tvb, seg_tree, offset, mask);
}
return offset;
}
/* Job Definition */
static gint
dissect_jobdef(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
{
proto_tree_add_item(seg_tree, hf_4607_jobdef_job_id, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sensor_type, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sensor_model, tvb, offset, 6, ENC_ASCII|ENC_NA);
offset += 6;
proto_tree_add_item(seg_tree, hf_4607_jobdef_filter, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_a, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_a, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_b, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_b, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_c, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_c, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_d, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_d, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_jobdef_radar_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_revisit_interval, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_along, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_cross, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_alt, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_heading, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_speed, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_slant, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_cross, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_vlos, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_mdv, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_prob, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_alarm, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_terrain_model, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
proto_tree_add_item(seg_tree, hf_4607_jobdef_geoid_model, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
return offset;
}
static gint
dissect_platform_location(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
{
proto_tree_add_item(seg_tree, hf_4607_platloc_time, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_platloc_latitude, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_platloc_longitude, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_platloc_altitude, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_platloc_track, tvb, offset, 2, ENC_BIG_ENDIAN);
offset += 2;
proto_tree_add_item(seg_tree, hf_4607_platloc_speed, tvb, offset, 4, ENC_BIG_ENDIAN);
offset += 4;
proto_tree_add_item(seg_tree, hf_4607_platloc_vertical_velocity, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
return offset;
}
/* 32 == packet header, 5 == segment type and length */
#define STANAG4607_MIN_LENGTH (32+5)
#define MINIMUM_SEGMENT_SIZE 14
#define MISSION_SEGMENT_SIZE 44
#define JOB_DEFINITION_SEGMENT_SIZE 73
#define PLATFORM_LOCATION_SEGMENT_SIZE 28
/* Provide a basic sanity check on segment sizes; the fixed-length
* ones should be what they claim to be.
*/
#define CHK_SIZE(SEG_TYPE) \
if (SEG_TYPE##_SIZE != seg_size) { \
col_append_str(pinfo->cinfo, COL_INFO, ", Error: Invalid segment size "); \
expert_add_info(pinfo, pi, &ei_bad_length); \
}
static int
dissect_stanag4607(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
guint32 offset = 0;
gint8 first_segment;
guint32 pkt_size = 0;
proto_item *ti = NULL;
proto_tree *hdr_tree = NULL;
proto_item *seg_type = NULL;
proto_tree *seg_tree = NULL;
guint8 seg_id = 0;
/* Basic length check */
if (tvb_captured_length(tvb) < STANAG4607_MIN_LENGTH)
return 0;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "S4607");
/* Clear out stuff in the info column */
col_clear(pinfo->cinfo, COL_INFO);
/* Put type of first segment in the info column */
first_segment = tvb_get_guint8(tvb, 32);
col_add_str(pinfo->cinfo, COL_INFO,
val_to_str(first_segment, stanag4607_segment_vals, "Unknown (0x%02x)"));
/* Put the timestamp, if available in the time column */
if (PLATFORM_LOCATION_SEGMENT == first_segment) {
guint32 millisecs;
nstime_t ts;
millisecs = tvb_get_ntohl(tvb, 37);
ts.secs = millisecs / 1000;
ts.nsecs = (int)((millisecs - 1000 * ts.secs) * 1000000);
col_set_time(pinfo->cinfo, COL_REL_TIME, &ts, "s4607.ploc.time");
}
/* The generic packet header */
if (tree) {
ti = proto_tree_add_item(tree, proto_stanag4607, tvb, 0, -1, ENC_NA);
hdr_tree = proto_item_add_subtree(ti, ett_4607_hdr);
proto_tree_add_item(hdr_tree, hf_4607_version, tvb, 0, 2, ENC_ASCII|ENC_NA);
ti = proto_tree_add_item(hdr_tree, hf_4607_packet_size, tvb, 2, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(hdr_tree, hf_4607_nationality, tvb, 6, 2, ENC_ASCII|ENC_NA);
proto_tree_add_item(hdr_tree, hf_4607_sec_class, tvb, 8, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(hdr_tree, hf_4607_sec_system, tvb, 9, 2, ENC_ASCII|ENC_NA);
proto_tree_add_item(hdr_tree, hf_4607_sec_code, tvb, 11, 2, ENC_BIG_ENDIAN);
proto_tree_add_item(hdr_tree, hf_4607_exercise_indicator, tvb, 13, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(hdr_tree, hf_4607_platform_id, tvb, 14, 10, ENC_ASCII|ENC_NA);
proto_tree_add_item(hdr_tree, hf_4607_mission_id, tvb, 24, 4, ENC_BIG_ENDIAN);
proto_tree_add_item(hdr_tree, hf_4607_job_id, tvb, 28, 4, ENC_BIG_ENDIAN);
}
offset = 32;
pkt_size = tvb_get_ntohl(tvb, 2);
/* Ruh ro. These should be equal... */
if (tvb_reported_length(tvb) != pkt_size) {
expert_add_info(pinfo, ti, &ei_bad_packet_size);
pkt_size = tvb_reported_length(tvb);
}
/* Loop over all segments in the packet */
while (offset < pkt_size) {
guint32 seg_size = 0;
guint32 saved_offset = offset;
proto_item * pi;
/* Segment header */
seg_type = proto_tree_add_item(hdr_tree, hf_4607_segment_type, tvb, offset, 1, ENC_BIG_ENDIAN);
seg_id = tvb_get_guint8(tvb, offset);
offset += 1;
seg_tree = proto_item_add_subtree(seg_type, ett_4607_seg);
pi = proto_tree_add_item(seg_tree, hf_4607_segment_size, tvb, offset, 4, ENC_BIG_ENDIAN);
seg_size = tvb_get_ntohl(tvb, offset);
offset += 4;
if (seg_size < MINIMUM_SEGMENT_SIZE) {
seg_size = MINIMUM_SEGMENT_SIZE;
col_append_str(pinfo->cinfo, COL_INFO, ", Error: Invalid segment size ");
expert_add_info(pinfo, pi, &ei_too_short);
}
switch (seg_id) {
case MISSION_SEGMENT:
CHK_SIZE(MISSION_SEGMENT);
offset = dissect_mission(tvb, seg_tree, offset);
break;
case DWELL_SEGMENT:
offset = dissect_dwell(tvb, seg_tree, offset);
break;
case JOB_DEFINITION_SEGMENT:
CHK_SIZE(JOB_DEFINITION_SEGMENT);
offset = dissect_jobdef(tvb, seg_tree, offset);
break;
case PLATFORM_LOCATION_SEGMENT:
CHK_SIZE(PLATFORM_LOCATION_SEGMENT);
offset = dissect_platform_location(tvb, seg_tree, offset);
break;
default:
offset += seg_size - 5;
break;
}
if (offset < saved_offset) {
/* overflow */
break;
}
}
return tvb_captured_length(tvb);
}
void
proto_register_stanag4607(void)
{
static hf_register_info hf[] = {
/* ========================================== */
/* Packet header */
{ &hf_4607_version,
{ "Version ID", "s4607.version",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_packet_size,
{ "Packet Size", "s4607.size",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_nationality,
{ "Nationality", "s4607.nationality",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_sec_class,
{ "Security Classification", "s4607.sec.class",
FT_UINT8, BASE_DEC,
VALS(stanag4607_class_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_sec_system,
{ "Security System", "s4607.sec.system",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_sec_code,
{ "Security Codes", "s4607.sec.codes",
FT_UINT16, BASE_HEX,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_exercise_indicator,
{ "Exercise Indicator", "s4607.exind",
FT_UINT8, BASE_DEC,
VALS(stanag4607_exind_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_platform_id,
{ "Platform ID", "s4607.platform",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_id,
{ "Mission ID", "s4607.mission",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_job_id,
{ "Job ID", "s4607.job",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* ========================================== */
/* Segment header */
{ &hf_4607_segment_type,
{ "Segment Type", "s4607.seg.type",
FT_UINT8, BASE_DEC,
VALS(stanag4607_segment_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_segment_size,
{ "Segment Size", "s4607.seg.size",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* ========================================== */
/* Dwell Segment */
{ &hf_4607_dwell_mask,
{ "Existence Mask", "s4607.dwell.mask",
FT_UINT64, BASE_HEX,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_revisit_index,
{ "Revisit Index", "s4607.dwell.revisit",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_dwell_index,
{ "Dwell Index", "s4607.dwell.dwell",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_last_dwell,
{ "Last Dwell of Revisit", "s4607.dwell.last",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_count,
{ "Target Report Count", "s4607.dwell.count",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_time,
{ "Dwell Time", "s4607.dwell.time",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_millisec), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_sensor_lat,
{ "Sensor Position Latitude", "s4607.dwell.sensor.lat",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_sensor_lon,
{ "Sensor Position Longitude", "s4607.dwell.sensor.lon",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_sensor_alt,
{ "Sensor Position Altitude", "s4607.dwell.sensor.alt",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_centimeters), 0x0,
NULL, HFILL }
},
/* D10 */
{ &hf_4607_dwell_scale_lat,
{ "Scale Factor, Latitude", "s4607.dwell.scale.lat",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_scale_lon,
{ "Scale Factor, Longitude", "s4607.dwell.scale.lon",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
/* D12 */
{ &hf_4607_dwell_unc_along,
{ "Sensor Position Uncertainty Along Track", "s4607.dwell.unc.along",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_centimeters), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_unc_cross,
{ "Sensor Position Uncertainty Cross Track", "s4607.dwell.unc.cross",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_centimeters), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_unc_alt,
{ "Sensor Position Uncertainty Altitude", "s4607.dwell.unc.alt",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_centimeters), 0x0,
NULL, HFILL }
},
/* D15 */
{ &hf_4607_dwell_track,
{ "Sensor Track", "s4607.dwell.track",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_ba16), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_speed,
{ "Sensor Speed", "s4607.dwell.speed",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_speed), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_vert_velocity,
{ "Sensor Vertical Velocity", "s4607.dwell.vvel",
FT_INT8, BASE_CUSTOM,
CF_FUNC(prt_speed_deci), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_track_unc,
{ "Sensor Track Uncertainty", "s4607.dwell.track.unc",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_speed_unc,
{ "Sensor Speed Uncertainty", "s4607.dwell.speed.unc",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_speed), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_vv_unc,
{ "Sensor Vertical Velocity Uncertainty", "s4607.dwell.vvel.unc",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_speed_centi), 0x0,
NULL, HFILL }
},
/* D21 */
{ &hf_4607_dwell_plat_heading,
{ "Platform Orientation Heading", "s4607.dwell.plat.heading",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_ba16), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_plat_pitch,
{ "Platform Orientation Pitch", "s4607.dwell.plat.pitch",
FT_INT16, BASE_CUSTOM,
CF_FUNC(prt_sa16), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_plat_roll,
{ "Platform Orientation Roll (Bank Angle)", "s4607.dwell.plat.roll",
FT_INT16, BASE_CUSTOM,
CF_FUNC(prt_sa16), 0x0,
NULL, HFILL }
},
/* D24 */
{ &hf_4607_dwell_da_lat,
{ "Dwell Area Center Latitude", "s4607.dwell.da.lat",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_da_lon,
{ "Dwell Area Center Longitude", "s4607.dwell.da.lon",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_da_range,
{ "Dwell Area Range Half Extent", "s4607.dwell.da.range",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_kilo), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_da_angle,
{ "Dwell Area Dwell Angle Half Extent", "s4607.dwell.da.angle",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_ba16), 0x0,
NULL, HFILL }
},
/* D28 */
{ &hf_4607_dwell_sensor_heading,
{ "Sensor Orientation Heading", "s4607.dwell.sensor.heading",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_ba16), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_sensor_pitch,
{ "Sensor Orientation Pitch", "s4607.dwell.sensor.pitch",
FT_INT16, BASE_CUSTOM,
CF_FUNC(prt_sa16), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_sensor_roll,
{ "Sensor Orientation Roll (Bank Angle)", "s4607.dwell.sensor.roll",
FT_INT16, BASE_CUSTOM,
CF_FUNC(prt_sa16), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_mdv,
{ "Minimum Detectable Velocity (MDV)", "s4607.dwell.mdv",
FT_UINT8, BASE_CUSTOM,
CF_FUNC(prt_speed_deci), 0x0,
NULL, HFILL }
},
/* ========================================== */
/* Target Report */
{ &hf_4607_dwell_report_index,
{ "MTI Report Index", "s4607.dwell.rpt.idx",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* D32.2 */
{ &hf_4607_dwell_report_lat,
{ "Target Location Hi-Res Latitude", "s4607.dwell.rpt.lat",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_lon,
{ "Target Location Hi-Res Longitude", "s4607.dwell.rpt.lon",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
/* D32.4 */
{ &hf_4607_dwell_report_delta_lat,
{ "Target Location Delta Latitude", "s4607.dwell.rpt.delta.lat",
FT_INT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_delta_lon,
{ "Target Location Delta Longitude", "s4607.dwell.rpt.delta.lon",
FT_INT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* D32.6 */
{ &hf_4607_dwell_report_height,
{ "Target Location Geodetic Height", "s4607.dwell.rpt.height",
FT_INT16, BASE_CUSTOM,
CF_FUNC(prt_meters), 0x0,
NULL, HFILL }
},
/* D32.7 */
{ &hf_4607_dwell_report_radial,
{ "Target Velocity Line of Sight Component", "s4607.dwell.rpt.radial",
FT_INT16, BASE_CUSTOM,
CF_FUNC(prt_speed_centi), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_wrap,
{ "Target Wrap Velocity", "s4607.dwell.rpt.wrap",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_speed_centi), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_snr,
{ "Target SNR", "s4607.dwell.rpt.snr",
FT_INT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_class,
{ "Target Classification", "s4607.dwell.rpt.class",
FT_UINT8, BASE_DEC,
VALS(stanag4607_target_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_prob,
{ "Target Class Probability", "s4607.dwell.rpt.prob",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* D32.12 */
{ &hf_4607_dwell_report_unc_slant,
{ "Target Measurement Uncertainty Slant Range", "s4607.dwell.rpt.unc.slant",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_centimeters), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_unc_cross,
{ "Target Measurement Uncertainty Cross Range", "s4607.dwell.rpt.unc.cross",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_decimeters), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_unc_height,
{ "Target Measurement Uncertainty Height", "s4607.dwell.rpt.unc.height",
FT_UINT8, BASE_CUSTOM,
CF_FUNC(prt_meters), 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_unc_radial,
{ "Target Measurement Uncertainty Radial Velocity", "s4607.dwell.rpt.unc.radial",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_speed_centi), 0x0,
NULL, HFILL }
},
/* D32.16 */
{ &hf_4607_dwell_report_tag_app,
{ "Truth Tag Application", "s4607.dwell.rpt.tag.app",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_tag_entity,
{ "Truth Tag Entity", "s4607.dwell.rpt.tag.entity",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_dwell_report_section,
{ "Radar Cross Section", "s4607.dwell.rpt.section",
FT_INT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* ========================================== */
/* Job Definition Segment */
{ &hf_4607_jobdef_job_id,
{ "Job ID", "s4607.job.id",
FT_UINT32, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sensor_type,
{ "Sensor Type", "s4607.job.type",
FT_UINT8, BASE_DEC,
VALS(stanag4607_sensor_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sensor_model,
{ "Sensor Model", "s4607.job.model",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_filter,
{ "Target Filtering Flag", "s4607.job.filter",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_priority,
{ "Radar Priority", "s4607.job.priority",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lat_a,
{ "Bounding Area Point A Latitude", "s4607.job.ba.lat.a",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lon_a,
{ "Bounding Area Point A Longitude", "s4607.job.ba.lon.a",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lat_b,
{ "Bounding Area Point B Latitude", "s4607.job.ba.lat.b",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lon_b,
{ "Bounding Area Point B Longitude", "s4607.job.ba.lon.b",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lat_c,
{ "Bounding Area Point C Latitude", "s4607.job.ba.lat.c",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lon_c,
{ "Bounding Area Point C Longitude", "s4607.job.ba.lon.c",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lat_d,
{ "Bounding Area Point D Latitude", "s4607.job.ba.lat.d",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_ba_lon_d,
{ "Bounding Area Point D Longitude", "s4607.job.ba.lon.d",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_radar_mode,
{ "Radar Mode", "s4607.job.mode",
FT_UINT8, BASE_DEC,
VALS(stanag4607_radar_mode_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_revisit_interval,
{ "Nominal Revisit Interval", "s4607.job.revisit",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_unc_along,
{ "Nominal Sensor Position Uncertainty Along Track", "s4607.job.unc.track",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_none16), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_unc_cross,
{ "Nominal Sensor Position Uncertainty Cross Track", "s4607.job.unc.cross",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_none16), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_unc_alt,
{ "Nominal Sensor Position Uncertainty Altitude", "s4607.job.unc.alt",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_none16), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_unc_heading,
{ "Nominal Sensor Position Uncertainty Track Heading", "s4607.job.unc.heading",
FT_UINT8, BASE_CUSTOM,
CF_FUNC(prt_none8), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_unc_speed,
{ "Nominal Sensor Position Uncertainty Speed", "s4607.job.unc.speed",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_none16), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sense_slant,
{ "Nominal Sensor Slant Range Standard Deviation", "s4607.job.sense.slant",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_none16), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sense_cross,
{ "Nominal Sensor Cross Range Standard Deviation", "s4607.job.sense.cross",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_ba16_none), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sense_vlos,
{ "Nominal Sensor Velocity Line-Of-Sight Std. Dev", "s4607.job.sense.vlos",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_none16), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sense_mdv,
{ "Nominal Sensor Minimum Detectable Velocity (MDV)", "s4607.job.sense.mdv",
FT_UINT8, BASE_CUSTOM,
CF_FUNC(prt_none8), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sense_prob,
{ "Nominal Sensor Detection Probability", "s4607.job.sense.prob",
FT_UINT8, BASE_CUSTOM,
CF_FUNC(prt_none8), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_sense_alarm,
{ "Nominal Sensor False Alarm Density", "s4607.job.sense.alarm",
FT_UINT8, BASE_CUSTOM,
CF_FUNC(prt_none8), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_terrain_model,
{ "Terrain Elevation Model Used", "s4607.job.terrain",
FT_UINT8, BASE_DEC,
VALS(stanag4607_terrain_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_jobdef_geoid_model,
{ "Geoid Model Used", "s4607.job.geoid",
FT_UINT8, BASE_DEC,
VALS(stanag4607_geoid_vals), 0x0,
NULL, HFILL }
},
/* ========================================== */
/* Mission segment */
{ &hf_4607_mission_plan,
{ "Mission Plan", "s4607.mission.plan",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_flight_plan,
{ "Mission Flight Plan", "s4607.mission.flight",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_platform,
{ "Mission Platform Type", "s4607.mission.platform",
FT_UINT8, BASE_DEC,
VALS(stanag4607_platform_vals), 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_platform_config,
{ "Mission Platform Configuration", "s4607.mission.config",
FT_STRING, BASE_NONE,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_time_year,
{ "Mission Reference Time Year", "s4607.mission.year",
FT_UINT16, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_time_month,
{ "Mission Reference Time Month", "s4607.mission.month",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
{ &hf_4607_mission_time_day,
{ "Mission Reference Time Day", "s4607.mission.day",
FT_UINT8, BASE_DEC,
NULL, 0x0,
NULL, HFILL }
},
/* ========================================== */
{ &hf_4607_platloc_time,
{ "Platform Location Time", "s4607.ploc.time",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_millisec), 0x0,
NULL, HFILL }
},
{ &hf_4607_platloc_latitude,
{ "Platform Position Latitude", "s4607.ploc.lat",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_sa32), 0x0,
NULL, HFILL }
},
{ &hf_4607_platloc_longitude,
{ "Platform Position Longitude", "s4607.ploc.lon",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_ba32), 0x0,
NULL, HFILL }
},
{ &hf_4607_platloc_altitude,
{ "Platform Position Altitude", "s4607.ploc.alt",
FT_INT32, BASE_CUSTOM,
CF_FUNC(prt_centimeters), 0x0,
NULL, HFILL }
},
{ &hf_4607_platloc_track,
{ "Platform Track", "s4607.ploc.track",
FT_UINT16, BASE_CUSTOM,
CF_FUNC(prt_ba16), 0x0,
NULL, HFILL }
},
{ &hf_4607_platloc_speed,
{ "Platform Speed", "s4607.ploc.speed",
FT_UINT32, BASE_CUSTOM,
CF_FUNC(prt_speed), 0x0,
NULL, HFILL }
},
{ &hf_4607_platloc_vertical_velocity,
{ "Platform Vertical Velocity", "s4607.ploc.velocity",
FT_INT8, BASE_CUSTOM,
CF_FUNC(prt_speed_deci), 0x0,
NULL, HFILL }
},
};
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_4607_hdr,
&ett_4607_seg,
&ett_4607_rpt,
};
static ei_register_info ei[] = {
{ &ei_too_short,
{ "s4607.segment_too_short", PI_MALFORMED, PI_ERROR,
"Segment size too small", EXPFILL }},
{ &ei_bad_length,
{ "s4607.segment_bad_length", PI_MALFORMED, PI_ERROR,
"Bad segment size", EXPFILL }},
{ &ei_bad_packet_size,
{ "s4607.bad_packet_size", PI_MALFORMED, PI_ERROR,
"Bad packet size field", EXPFILL }}
};
expert_module_t* expert_4607;
proto_stanag4607 = proto_register_protocol (
"STANAG 4607 (GMTI Format)", /* name */
"STANAG 4607", /* short name */
"s4607" /* abbrev */
);
proto_register_field_array(proto_stanag4607, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
expert_4607 = expert_register_protocol(proto_stanag4607);
expert_register_field_array(expert_4607, ei, array_length(ei));
stanag4607_handle = register_dissector("STANAG 4607", dissect_stanag4607, proto_stanag4607);
/* prefs_register_protocol(proto_stanag4607, proto_reg_handoff_stanag4607); */
}
void
proto_reg_handoff_stanag4607(void)
{
dissector_add_uint("wtap_encap", WTAP_ENCAP_STANAG_4607, stanag4607_handle);
}
/*
* Editor modelines - https://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 8
* tab-width: 8
* indent-tabs-mode: t
* End:
*
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
* :indentSize=8:tabSize=8:noTabs=false:
*/