1 /* packet-stanag4607.c
2  * Routines for STANAG 4607 dissection
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 #include "config.h"
7 
8 #include <math.h>
9 #include <epan/packet.h>
10 #include <epan/expert.h>
11 
12 #include <wiretap/stanag4607.h>
13 
14 void proto_register_stanag4607(void);
15 void proto_reg_handoff_stanag4607(void);
16 
17 static int proto_stanag4607 = -1;
18 
19 static int hf_4607_version = -1;
20 static int hf_4607_packet_size = -1;
21 static int hf_4607_nationality = -1;
22 static int hf_4607_sec_class = -1;
23 static int hf_4607_sec_system = -1;
24 static int hf_4607_sec_code = -1;
25 static int hf_4607_exercise_indicator = -1;
26 static int hf_4607_platform_id = -1;
27 static int hf_4607_mission_id = -1;
28 static int hf_4607_job_id = -1;
29 
30 static int hf_4607_segment_type = -1;
31 static int hf_4607_segment_size = -1;
32 
33 /* Mission Segment */
34 static int hf_4607_mission_plan = -1;
35 static int hf_4607_mission_flight_plan = -1;
36 static int hf_4607_mission_platform = -1;
37 static int hf_4607_mission_platform_config = -1;
38 static int hf_4607_mission_time_year = -1;
39 static int hf_4607_mission_time_month = -1;
40 static int hf_4607_mission_time_day = -1;
41 
42 /* Dwell Segment */
43 static int hf_4607_dwell_mask = -1;
44 static int hf_4607_dwell_revisit_index = -1;
45 static int hf_4607_dwell_dwell_index = -1;
46 static int hf_4607_dwell_last_dwell = -1;
47 static int hf_4607_dwell_count = -1;
48 static int hf_4607_dwell_time = -1;
49 static int hf_4607_dwell_sensor_lat = -1;
50 static int hf_4607_dwell_sensor_lon = -1;
51 static int hf_4607_dwell_sensor_alt = -1;
52 static int hf_4607_dwell_scale_lat = -1;
53 static int hf_4607_dwell_scale_lon = -1;
54 static int hf_4607_dwell_unc_along = -1;
55 static int hf_4607_dwell_unc_cross = -1;
56 static int hf_4607_dwell_unc_alt = -1;
57 static int hf_4607_dwell_track = -1;
58 static int hf_4607_dwell_speed = -1;
59 static int hf_4607_dwell_vert_velocity = -1;
60 static int hf_4607_dwell_track_unc = -1;
61 static int hf_4607_dwell_speed_unc = -1;
62 static int hf_4607_dwell_vv_unc = -1;
63 
64 static int hf_4607_dwell_plat_heading = -1;
65 static int hf_4607_dwell_plat_pitch = -1;
66 static int hf_4607_dwell_plat_roll = -1;
67 static int hf_4607_dwell_da_lat = -1;
68 static int hf_4607_dwell_da_lon = -1;
69 static int hf_4607_dwell_da_range = -1;
70 static int hf_4607_dwell_da_angle = -1;
71 static int hf_4607_dwell_sensor_heading = -1;
72 static int hf_4607_dwell_sensor_pitch = -1;
73 static int hf_4607_dwell_sensor_roll = -1;
74 static int hf_4607_dwell_mdv = -1;
75 
76 /* Target Report */
77 static int hf_4607_dwell_report_index = -1;
78 static int hf_4607_dwell_report_lat = -1;
79 static int hf_4607_dwell_report_lon = -1;
80 static int hf_4607_dwell_report_delta_lat = -1;
81 static int hf_4607_dwell_report_delta_lon = -1;
82 static int hf_4607_dwell_report_height = -1;
83 static int hf_4607_dwell_report_radial = -1;
84 static int hf_4607_dwell_report_wrap = -1;
85 static int hf_4607_dwell_report_snr = -1;
86 static int hf_4607_dwell_report_class = -1;
87 static int hf_4607_dwell_report_prob = -1;
88 static int hf_4607_dwell_report_unc_slant = -1;
89 static int hf_4607_dwell_report_unc_cross = -1;
90 static int hf_4607_dwell_report_unc_height = -1;
91 static int hf_4607_dwell_report_unc_radial = -1;
92 static int hf_4607_dwell_report_tag_app = -1;
93 static int hf_4607_dwell_report_tag_entity = -1;
94 static int hf_4607_dwell_report_section = -1;
95 
96 /* Job Definition Segment */
97 static int hf_4607_jobdef_job_id = -1;
98 static int hf_4607_jobdef_sensor_type = -1;
99 static int hf_4607_jobdef_sensor_model = -1;
100 static int hf_4607_jobdef_filter = -1;
101 static int hf_4607_jobdef_priority = -1;
102 static int hf_4607_jobdef_ba_lat_a = -1;
103 static int hf_4607_jobdef_ba_lon_a = -1;
104 static int hf_4607_jobdef_ba_lat_b = -1;
105 static int hf_4607_jobdef_ba_lon_b = -1;
106 static int hf_4607_jobdef_ba_lat_c = -1;
107 static int hf_4607_jobdef_ba_lon_c = -1;
108 static int hf_4607_jobdef_ba_lat_d = -1;
109 static int hf_4607_jobdef_ba_lon_d = -1;
110 static int hf_4607_jobdef_radar_mode = -1;
111 static int hf_4607_jobdef_revisit_interval = -1;
112 static int hf_4607_jobdef_unc_along = -1;
113 static int hf_4607_jobdef_unc_cross = -1;
114 static int hf_4607_jobdef_unc_alt = -1;
115 static int hf_4607_jobdef_unc_heading = -1;
116 static int hf_4607_jobdef_unc_speed = -1;
117 static int hf_4607_jobdef_sense_slant = -1;
118 static int hf_4607_jobdef_sense_cross = -1;
119 static int hf_4607_jobdef_sense_vlos = -1;
120 static int hf_4607_jobdef_sense_mdv = -1;
121 static int hf_4607_jobdef_sense_prob = -1;
122 static int hf_4607_jobdef_sense_alarm = -1;
123 static int hf_4607_jobdef_terrain_model = -1;
124 static int hf_4607_jobdef_geoid_model = -1;
125 
126 /* Platform Location Segment */
127 static int hf_4607_platloc_time = -1;
128 static int hf_4607_platloc_latitude = -1;
129 static int hf_4607_platloc_longitude = -1;
130 static int hf_4607_platloc_altitude = -1;
131 static int hf_4607_platloc_track = -1;
132 static int hf_4607_platloc_speed = -1;
133 static int hf_4607_platloc_vertical_velocity = -1;
134 
135 /* Subtree pointers */
136 static gint ett_4607_hdr = -1;
137 static gint ett_4607_seg = -1;
138 static gint ett_4607_rpt = -1;
139 
140 /* Error pointers */
141 static expert_field ei_bad_length      = EI_INIT;
142 static expert_field ei_too_short       = EI_INIT;
143 static expert_field ei_bad_packet_size = EI_INIT;
144 
145 static dissector_handle_t stanag4607_handle;
146 
147 
148 static const value_string stanag4607_class_vals[] = {
149 	{   1, "TOP SECRET" },
150 	{   2, "SECRET" },
151 	{   3, "CONFIDENTIAL" },
152 	{   4, "RESTRICTED" },
153 	{   5, "UNCLASSIFIED" },
154 	{ 0, NULL }
155 };
156 
157 static const value_string stanag4607_exind_vals[] = {
158 	{   0, "Operation, Real Data" },
159 	{   1, "Operation, Simulated Data" },
160 	{   2, "Operation, Synthesized Data" },
161 	{   128, "Exercise, Real Data" },
162 	{   129, "Exercise, Simulated Data" },
163 	{   130, "Exercise, Synthesized Data" },
164 	{ 0, NULL }
165 };
166 
167 #define MISSION_SEGMENT 1
168 #define DWELL_SEGMENT 2
169 #define JOB_DEFINITION_SEGMENT 5
170 #define PLATFORM_LOCATION_SEGMENT 13
171 
172 static const value_string stanag4607_segment_vals[] = {
173 	{   1, "Mission Segment" },
174 	{   2, "Dwell Segment" },
175 	{   3, "HRR Segment" },
176 	{   5, "Job Definition Segment" },
177 	{   6, "Free Text Segment" },
178 	{   7, "Low Reflectivity Index Segment" },
179 	{   8, "Group Segment" },
180 	{   9, "Attached Target Segment" },
181 	{  10, "Test and Status Segment" },
182 	{  11, "System-Specific Segment" },
183 	{  12, "Processing History Segment" },
184 	{  13, "Platform Location Segment" },
185 	{  101, "Job Request Segment" },
186 	{  102, "Job Acknowledgment Segment" },
187 	{ 0, NULL }
188 };
189 
190 static const value_string stanag4607_sensor_vals[] = {
191 	{   0, "Unidentified" },
192 	{   1, "Other" },
193 	{   2, "HiSAR" },
194 	{   3, "ASTOR" },
195 	{   4, "Rotary Wing Radar" },
196 	{   5, "Global Hawk Sensor" },
197 	{   6, "HORIZON" },
198 	{   7, "APY-3" },
199 	{   8, "APY-6" },
200 	{   9, "APY-8 (Lynx I)" },
201 	{  10, "RADARSAT2" },
202 	{  11, "ASARS-2A" },
203 	{  12, "TESAR" },
204 	{  13, "MP-RTIP" },
205 	{  14, "APG-77" },
206 	{  15, "APG-79" },
207 	{  16, "APG-81" },
208 	{  17, "APY-6v1" },
209 	{  18, "SPY-I (Lynx II)" },
210 	{  19, "SIDM" },
211 	{  20, "LIMIT" },
212 	{  21, "TCAR (AGS A321)" },
213 	{  22, "LSRS Sensor" },
214 	{  23, "UGS Single Sensor" },
215 	{  24, "UGS Cluster Sensor" },
216 	{  25, "IMASTER GMTI" },
217 	{  26, "AN/ZPY-1 (STARLite)" },
218 	{  27, "VADER" },
219 	{  255, "No Statement" },
220 	{ 0, NULL }
221 };
222 
223 static const value_string stanag4607_radar_mode_vals[] = {
224 	{   0, "Unspecified Mode" },
225 	{   1, "MTI (Moving Target Indicator)" },
226 	{   2, "HRR (High Range Resolution)" },
227 	{   3, "UHRR (Ultra High Range Resolution)" },
228 	{   4, "HUR (High Update Rate)" },
229 	{   5, "FTI" },
230 	/* TODO: and many many more ... */
231 	{ 0, NULL }
232 };
233 
234 static const value_string stanag4607_terrain_vals[] = {
235 	{   0, "None Specified" },
236 	{   1, "DTED0 (Digital Terrain Elevation Data, Level 0)" },
237 	{   2, "DTED1 (Digital Terrain Elevation Data, Level 1)" },
238 	{   3, "DTED2 (Digital Terrain Elevation Data, Level 2)" },
239 	{   4, "DTED3 (Digital Terrain Elevation Data, Level 3)" },
240 	{   5, "DTED4 (Digital Terrain Elevation Data, Level 4)" },
241 	{   6, "DTED5 (Digital Terrain Elevation Data, Level 5)" },
242 	{   7, "SRTM1 (Shuttle Radar Topography Mission, Level 1)" },
243 	{   8, "SRTM2 (Shuttle Radar Topography Mission, Level 2)" },
244 	{   9, "DGM50 M745 (Digitales Gelandemodell 1:50 000)" },
245 	{   10, "DGM250 (Digitales Gelandemodell 1:250 000)" },
246 	{   11, "ITHD (Interferometric Terrain Data Height)" },
247 	{   12, "STHD (Stereometric Terrain Data Height)" },
248 	{   13, "SEDRIS (SEDRIS Reference Model ISO/IEC 18026)" },
249 	{ 0, NULL }
250 };
251 
252 static const value_string stanag4607_geoid_vals[] = {
253 	{   0, "None Specified" },
254 	{   1, "EGM96 (Earth Gravitional Model, Version 1996)" },
255 	{   2, "GEO96 (Geoid Gravitional Model, Version 1996)" },
256 	{   3, "Flat Earth" },
257 	{ 0, NULL }
258 };
259 
260 static const value_string stanag4607_target_vals[] = {
261 	{   0, "No Information, Live Target" },
262 	{   1, "Tracked Vehicle, Live Target" },
263 	{   2, "Wheeled Vehicle, Live Target" },
264 	{   3, "Rotary Wing Aircraft, Live Target" },
265 	{   4, "Fixed Wing Aircraft, Live Target" },
266 	{   5, "Stationary Rotator, Live Target" },
267 	{   6, "Maritime, Live Target" },
268 	{   7, "Beacon, Live Target" },
269 	{   8, "Amphibious, Live Target" },
270 	{   9, "Person, Live Target" },
271 	{   10, "Vehicle, Live Target" },
272 	{   11, "Animal, Live Target" },
273 	{   12, "Large Multiple-Return, Live Land Target" },
274 	{   13, "Large Multiple-Return, Live Maritime Target" },
275 
276 	{   126, "Other, Live Target" },
277 	{   127, "Unknown, Live Target" },
278 	{   128, "No Information, Simulated Target" },
279 	{   129, "Tracked Vehicle, Simulated Target" },
280 	{   130, "Wheeled Vehicle, Simulated Target" },
281 	{   131, "Rotary Wing Aircraft, Simulated Target" },
282 	{   132, "Fixed Wing Aircraft, Simulated Target" },
283 	{   133, "Stationary Rotator, Simulated Target" },
284 	{   134, "Maritme, Simulated Target" },
285 	{   135, "Beacon, Simulated Target" },
286 	{   136, "Amphibious, Simulated Target" },
287 	{   137, "Person, Simulated Target" },
288 	{   138, "Vehicle, Simulated Target" },
289 	{   139, "Animal, Simulated Target" },
290 	{   140, "Large Multiple-Return, Simulated Land Target" },
291 	{   141, "Large Multiple-Return, Simulated Maritime Target" },
292 
293 	{   143, "Tagging Device" },
294 
295 	{   254, "Other, Simulated Target" },
296 	{   255, "Unknown, Simulated Target" },
297 	{ 0, NULL }
298 };
299 
300 static const value_string stanag4607_platform_vals[] = {
301 	{   0, "Unidentified" },
302 	{   1, "ACS" },
303 	{   2, "ARL-M" },
304 	{   3, "Sentinel" },
305 	{   4, "Rotary Wing Radar" },
306 	{   5, "Global Hawk-Navy" },
307 	{   6, "HORIZON" },
308 	{   7, "E-8 (Joint STARS)" },
309 	{   8, "P-3C" },
310 	{   9, "Predator" },
311 	{  10, "RADARSAT2" },
312 	{  11, "U-2" },
313 	{  12, "E-10" },
314 	{  13, "UGS - Single" },
315 	{  14, "UGS - Cluster" },
316 	{  15, "Ground Based" },
317 	{  16, "UAV-Army" },
318 	{  17, "UAV-Marines" },
319 	{  18, "UAV-Navy" },
320 	{  19, "UAV-Air Force" },
321 	{  20, "Global Hawk-Air Force" },
322 	{  21, "Global Hawk-Australia" },
323 	{  22, "Global Hawk-Germany" },
324 	{  23, "Paul Revere" },
325 	{  24, "Mariner UAV" },
326 	{  25, "BAC-111" },
327 	{  26, "Coyote" },
328 	{  27, "King Air" },
329 	{  28, "LIMIT" },
330 	{  29, "NRL NP-3B" },
331 	{  30, "SOSTAR-X" },
332 	{  31, "WatchKeeper" },
333 	{  32, "Alliance Ground Surveillance (AGS) (A321)" },
334 	{  33, "Stryker" },
335 	{  34, "AGS (HALE UAV)" },
336 	{  35, "SIDM" },
337 	{  36, "Reaper" },
338 	{  37, "Warrior A" },
339 	{  38, "Warrior" },
340 	{  39, "Twin Otter" },
341 	{  255, "Other" },
342 	{ 0, NULL }
343 };
344 
345 static void
prt_sa32(gchar * buff,guint32 val)346 prt_sa32(gchar *buff, guint32 val)
347 {
348 	double deg, min, sec;
349 	double x = (double) ((gint32) val);
350 	x /= (double) (1UL<<30);
351 	x *= 45.0;
352 	deg = floor(x);
353 	min = floor(60.0 * (x - deg));
354 	sec = 60.0 * (60.0 * (x - deg) - min);
355 	/* checkAPI.pl doesn't like the unicode degree symbol, I don't know what to do... */
356 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.8f degrees (%.0f %.0f\' %.2f\")", x, deg, min, sec);
357 }
358 
359 static void
prt_ba32(gchar * buff,guint32 val)360 prt_ba32(gchar *buff, guint32 val)
361 {
362 	double deg, min, sec;
363 	double x = (double) val;
364 	x /= (double) (1UL<<30);
365 	x *= 90.0;
366 	deg = floor(x);
367 	min = floor(60.0 * (x - deg));
368 	sec = 60.0 * (60.0 * (x - deg) - min);
369 	/* checkAPI.pl doesn't like the unicode degree symbol, I don't know what to do... */
370 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.8f degrees (%.0f %.0f\' %.2f\")", x, deg, min, sec);
371 }
372 
373 static void
prt_sa16(gchar * buff,guint32 val)374 prt_sa16(gchar *buff, guint32 val)
375 {
376 	double x = (double) ((gint32) val);
377 	x /= (double) (1<<14);
378 	x *= 90.0;
379 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f degrees", x);
380 }
381 
382 static void
prt_ba16(gchar * buff,guint32 val)383 prt_ba16(gchar *buff, guint32 val)
384 {
385 	double x = (double) val;
386 	x /= (double) (1<<14);
387 	x *= 90.0;
388 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f degrees", x);
389 }
390 
391 static void
prt_ba16_none(gchar * buff,guint32 val)392 prt_ba16_none(gchar *buff, guint32 val)
393 {
394 	double x = (double) val;
395 	x /= (double) (1<<14);
396 	x *= 90.0;
397 	if (val <= 65536)
398 		g_snprintf(buff, ITEM_LABEL_LENGTH, "No Statement");
399 	else
400 		g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f degrees", x);
401 }
402 
403 static void
prt_kilo(gchar * buff,guint32 val)404 prt_kilo(gchar *buff, guint32 val)
405 {
406 	double x = (double) ((gint32) val);
407 	x /= 128.0;
408 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.2f kilometers", x);
409 }
410 
411 static void
prt_meters(gchar * buff,guint32 val)412 prt_meters(gchar *buff, guint32 val)
413 {
414 	double x = (double) ((gint32) val);
415 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.0f meters", x);
416 }
417 
418 static void
prt_decimeters(gchar * buff,guint32 val)419 prt_decimeters(gchar *buff, guint32 val)
420 {
421 	double x = (double) ((gint32) val);
422 	x /= 10.0;
423 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.1f meters", x);
424 }
425 
426 static void
prt_centimeters(gchar * buff,guint32 val)427 prt_centimeters(gchar *buff, guint32 val)
428 {
429 	double x = (double) ((gint32) val);
430 	x /= 100.0;
431 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.2f meters", x);
432 }
433 
434 static void
prt_speed(gchar * buff,guint32 val)435 prt_speed(gchar *buff, guint32 val)
436 {
437 	double x = (double) val;
438 	x /= 1000.0;
439 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f meters/second", x);
440 }
441 
442 static void
prt_speed_centi(gchar * buff,guint32 val)443 prt_speed_centi(gchar *buff, guint32 val)
444 {
445 	double x = (double) ((gint32) val);
446 	x /= 100.0;
447 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.2f meters/second", x);
448 }
449 
450 static void
prt_speed_deci(gchar * buff,guint32 val)451 prt_speed_deci(gchar *buff, guint32 val)
452 {
453 	/* Usually 8-bit, signed */
454 	double x = (double) ((gint32) val);
455 	x /= 10.0;
456 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.1f meters/second", x);
457 }
458 
459 static void
prt_millisec(gchar * buff,guint32 val)460 prt_millisec(gchar *buff, guint32 val)
461 {
462 	double x = (double) val;
463 	x /= 1000.0;
464 	g_snprintf(buff, ITEM_LABEL_LENGTH, "%.3f seconds", x);
465 }
466 
467 static void
prt_none8(gchar * buff,guint32 val)468 prt_none8(gchar *buff, guint32 val)
469 {
470 	if (0xff == val)
471 		g_snprintf(buff, ITEM_LABEL_LENGTH, "No Statement");
472 	else
473 		g_snprintf(buff, ITEM_LABEL_LENGTH, "%d", val);
474 }
475 
476 static void
prt_none16(gchar * buff,guint32 val)477 prt_none16(gchar *buff, guint32 val)
478 {
479 	if (0xffff == val)
480 		g_snprintf(buff, ITEM_LABEL_LENGTH, "No Statement");
481 	else
482 		g_snprintf(buff, ITEM_LABEL_LENGTH, "%d", val);
483 }
484 
485 
486 static gint
dissect_mission(tvbuff_t * tvb,proto_tree * seg_tree,gint offset)487 dissect_mission(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
488 {
489 	proto_tree_add_item(seg_tree, hf_4607_mission_plan, tvb, offset, 12, ENC_ASCII|ENC_NA);
490 	offset += 12;
491 	proto_tree_add_item(seg_tree, hf_4607_mission_flight_plan, tvb, offset, 12, ENC_ASCII|ENC_NA);
492 	offset += 12;
493 	proto_tree_add_item(seg_tree, hf_4607_mission_platform, tvb, offset, 1, ENC_BIG_ENDIAN);
494 	offset += 1;
495 	proto_tree_add_item(seg_tree, hf_4607_mission_platform_config, tvb, offset, 10, ENC_ASCII|ENC_NA);
496 	offset += 10;
497 	proto_tree_add_item(seg_tree, hf_4607_mission_time_year, tvb, offset, 2, ENC_BIG_ENDIAN);
498 	offset += 2;
499 	proto_tree_add_item(seg_tree, hf_4607_mission_time_month, tvb, offset, 1, ENC_BIG_ENDIAN);
500 	offset += 1;
501 	proto_tree_add_item(seg_tree, hf_4607_mission_time_day, tvb, offset, 1, ENC_BIG_ENDIAN);
502 	offset += 1;
503 
504 	return offset;
505 }
506 
507 /* Dwell Segment Existence Mask */
508 /* The Dxx fields are NOT bit locations! They are the field numbers
509  * as specified in Table 2-4 Dwell Segment.  These field numbers DO NOT
510  * count bit locations in the existence mask (even though they come
511  * close to this).  The m and n values of the m*8+n offset below are
512  * given in Figure 2-1 titled "Dwell Segment Existence Mask Mapping."
513  */
514 #define SET(MASK,OFF) (((MASK)>>(OFF)) & G_GINT64_CONSTANT(1))
515 #define D10     6*8+7
516 #define D12     6*8+5
517 #define D15     6*8+2
518 #define D18     5*8+7
519 #define D21     5*8+4
520 #define D24     5*8+1
521 #define D28     4*8+5
522 #define D31     4*8+2
523 #define D32_1   4*8+1
524 #define D32_2   4*8+0
525 #define D32_6   3*8+4
526 #define D32_7   3*8+3
527 #define D32_9   3*8+1
528 #define D32_10  3*8+0
529 #define D32_11  2*8+7
530 #define D32_12  2*8+6
531 #define D32_16  2*8+2
532 #define D32_18  2*8+0
533 
534 /* Target Report */
535 static gint
dissect_target(tvbuff_t * tvb,proto_tree * seg_tree,gint offset,guint64 mask)536 dissect_target(tvbuff_t *tvb, proto_tree *seg_tree, gint offset, guint64 mask)
537 {
538 	proto_item *rpt_item = NULL;
539 	proto_tree *rpt_tree = seg_tree;
540 
541 	if (SET(mask, D32_1)) {
542 		rpt_item = proto_tree_add_item(rpt_tree, hf_4607_dwell_report_index, tvb, offset, 2, ENC_BIG_ENDIAN);
543 		offset += 2;
544 		rpt_tree = proto_item_add_subtree(rpt_item, ett_4607_rpt);
545 	}
546 
547 	if (SET(mask, D32_2)) {
548 		rpt_item = proto_tree_add_item(rpt_tree, hf_4607_dwell_report_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
549 		offset += 4;
550 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
551 		offset += 4;
552 	} else {
553 		rpt_item = proto_tree_add_item(rpt_tree, hf_4607_dwell_report_delta_lat, tvb, offset, 2, ENC_BIG_ENDIAN);
554 		offset += 2;
555 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_delta_lon, tvb, offset, 2, ENC_BIG_ENDIAN);
556 		offset += 2;
557 	}
558 
559 	/* If the report index wasn't set, then no subtree yet */
560 	if (rpt_item && rpt_tree == seg_tree) {
561 		rpt_tree = proto_item_add_subtree(rpt_item, ett_4607_rpt);
562 	}
563 	if (SET(mask, D32_6)) {
564 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_height, tvb, offset, 2, ENC_BIG_ENDIAN);
565 		offset += 2;
566 	}
567 	if (SET(mask, D32_7)) {
568 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_radial, tvb, offset, 2, ENC_BIG_ENDIAN);
569 		offset += 2;
570 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_wrap, tvb, offset, 2, ENC_BIG_ENDIAN);
571 		offset += 2;
572 	}
573 	if (SET(mask, D32_9)) {
574 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_snr, tvb, offset, 1, ENC_BIG_ENDIAN);
575 		offset += 1;
576 	}
577 	if (SET(mask, D32_10)) {
578 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_class, tvb, offset, 1, ENC_BIG_ENDIAN);
579 		offset += 1;
580 	}
581 	if (SET(mask, D32_11)) {
582 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_prob, tvb, offset, 1, ENC_BIG_ENDIAN);
583 		offset += 1;
584 	}
585 	if (SET(mask, D32_12)) {
586 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_slant, tvb, offset, 2, ENC_BIG_ENDIAN);
587 		offset += 2;
588 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_cross, tvb, offset, 2, ENC_BIG_ENDIAN);
589 		offset += 2;
590 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_height, tvb, offset, 1, ENC_BIG_ENDIAN);
591 		offset += 1;
592 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_unc_radial, tvb, offset, 2, ENC_BIG_ENDIAN);
593 		offset += 2;
594 	}
595 	if (SET(mask, D32_16)) {
596 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_tag_app, tvb, offset, 1, ENC_BIG_ENDIAN);
597 		offset += 1;
598 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_tag_entity, tvb, offset, 4, ENC_BIG_ENDIAN);
599 		offset += 4;
600 	}
601 	if (SET(mask, D32_18)) {
602 		proto_tree_add_item(rpt_tree, hf_4607_dwell_report_section, tvb, offset, 1, ENC_BIG_ENDIAN);
603 		offset += 1;
604 	}
605 
606 	return offset;
607 }
608 
609 /* Dwell Segment */
610 static gint
dissect_dwell(tvbuff_t * tvb,proto_tree * seg_tree,gint offset)611 dissect_dwell(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
612 {
613 	guint64 mask;
614 	guint32 count;
615 
616 	mask = tvb_get_ntoh64(tvb, offset);
617 
618 	proto_tree_add_item(seg_tree, hf_4607_dwell_mask, tvb, offset, 8, ENC_BIG_ENDIAN);
619 	offset += 8;
620 	proto_tree_add_item(seg_tree, hf_4607_dwell_revisit_index, tvb, offset, 2, ENC_BIG_ENDIAN);
621 	offset += 2;
622 	proto_tree_add_item(seg_tree, hf_4607_dwell_dwell_index, tvb, offset, 2, ENC_BIG_ENDIAN);
623 	offset += 2;
624 	proto_tree_add_item(seg_tree, hf_4607_dwell_last_dwell, tvb, offset, 1, ENC_BIG_ENDIAN);
625 	offset += 1;
626 
627 	/* count of target reports */
628 	count = tvb_get_ntohs(tvb, offset);
629 	proto_tree_add_item(seg_tree, hf_4607_dwell_count, tvb, offset, 2, ENC_BIG_ENDIAN);
630 	offset += 2;
631 	proto_tree_add_item(seg_tree, hf_4607_dwell_time, tvb, offset, 4, ENC_BIG_ENDIAN);
632 	offset += 4;
633 	proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
634 	offset += 4;
635 	proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
636 	offset += 4;
637 	proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_alt, tvb, offset, 4, ENC_BIG_ENDIAN);
638 	offset += 4;
639 
640 	if (SET(mask, D10)) {
641 		proto_tree_add_item(seg_tree, hf_4607_dwell_scale_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
642 		offset += 4;
643 		proto_tree_add_item(seg_tree, hf_4607_dwell_scale_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
644 		offset += 4;
645 	}
646 	if (SET(mask, D12)) {
647 		proto_tree_add_item(seg_tree, hf_4607_dwell_unc_along, tvb, offset, 4, ENC_BIG_ENDIAN);
648 		offset += 4;
649 		proto_tree_add_item(seg_tree, hf_4607_dwell_unc_cross, tvb, offset, 4, ENC_BIG_ENDIAN);
650 		offset += 4;
651 		proto_tree_add_item(seg_tree, hf_4607_dwell_unc_alt, tvb, offset, 2, ENC_BIG_ENDIAN);
652 		offset += 2;
653 	}
654 	if (SET(mask, D15)) {
655 		proto_tree_add_item(seg_tree, hf_4607_dwell_track, tvb, offset, 2, ENC_BIG_ENDIAN);
656 		offset += 2;
657 		proto_tree_add_item(seg_tree, hf_4607_dwell_speed, tvb, offset, 4, ENC_BIG_ENDIAN);
658 		offset += 4;
659 		proto_tree_add_item(seg_tree, hf_4607_dwell_vert_velocity, tvb, offset, 1, ENC_BIG_ENDIAN);
660 		offset += 1;
661 	}
662 	if (SET(mask, D18)) {
663 		proto_tree_add_item(seg_tree, hf_4607_dwell_track_unc, tvb, offset, 1, ENC_BIG_ENDIAN);
664 		offset += 1;
665 		proto_tree_add_item(seg_tree, hf_4607_dwell_speed_unc, tvb, offset, 2, ENC_BIG_ENDIAN);
666 		offset += 2;
667 		proto_tree_add_item(seg_tree, hf_4607_dwell_vv_unc, tvb, offset, 2, ENC_BIG_ENDIAN);
668 		offset += 2;
669 	}
670 	if (SET(mask, D21)) {
671 		proto_tree_add_item(seg_tree, hf_4607_dwell_plat_heading, tvb, offset, 2, ENC_BIG_ENDIAN);
672 		offset += 2;
673 		proto_tree_add_item(seg_tree, hf_4607_dwell_plat_pitch, tvb, offset, 2, ENC_BIG_ENDIAN);
674 		offset += 2;
675 		proto_tree_add_item(seg_tree, hf_4607_dwell_plat_roll, tvb, offset, 2, ENC_BIG_ENDIAN);
676 		offset += 2;
677 	}
678 
679 	/* Mandatory Dwell Area */
680 	proto_tree_add_item(seg_tree, hf_4607_dwell_da_lat, tvb, offset, 4, ENC_BIG_ENDIAN);
681 	offset += 4;
682 	proto_tree_add_item(seg_tree, hf_4607_dwell_da_lon, tvb, offset, 4, ENC_BIG_ENDIAN);
683 	offset += 4;
684 	proto_tree_add_item(seg_tree, hf_4607_dwell_da_range, tvb, offset, 2, ENC_BIG_ENDIAN);
685 	offset += 2;
686 	proto_tree_add_item(seg_tree, hf_4607_dwell_da_angle, tvb, offset, 2, ENC_BIG_ENDIAN);
687 	offset += 2;
688 
689 	if (SET(mask, D28)) {
690 		proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_heading, tvb, offset, 2, ENC_BIG_ENDIAN);
691 		offset += 2;
692 		proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_pitch, tvb, offset, 2, ENC_BIG_ENDIAN);
693 		offset += 2;
694 		proto_tree_add_item(seg_tree, hf_4607_dwell_sensor_roll, tvb, offset, 2, ENC_BIG_ENDIAN);
695 		offset += 2;
696 	}
697 	if (SET(mask, D31)) {
698 		proto_tree_add_item(seg_tree, hf_4607_dwell_mdv, tvb, offset, 1, ENC_BIG_ENDIAN);
699 		offset += 1;
700 	}
701 
702 	while (count--) {
703 		offset = dissect_target(tvb, seg_tree, offset, mask);
704 	}
705 
706 	return offset;
707 }
708 
709 /* Job Definition */
710 static gint
dissect_jobdef(tvbuff_t * tvb,proto_tree * seg_tree,gint offset)711 dissect_jobdef(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
712 {
713 	proto_tree_add_item(seg_tree, hf_4607_jobdef_job_id, tvb, offset, 4, ENC_BIG_ENDIAN);
714 	offset += 4;
715 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sensor_type, tvb, offset, 1, ENC_BIG_ENDIAN);
716 	offset += 1;
717 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sensor_model, tvb, offset, 6, ENC_ASCII|ENC_NA);
718 	offset += 6;
719 	proto_tree_add_item(seg_tree, hf_4607_jobdef_filter, tvb, offset, 1, ENC_BIG_ENDIAN);
720 	offset += 1;
721 	proto_tree_add_item(seg_tree, hf_4607_jobdef_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
722 	offset += 1;
723 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_a, tvb, offset, 4, ENC_BIG_ENDIAN);
724 	offset += 4;
725 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_a, tvb, offset, 4, ENC_BIG_ENDIAN);
726 	offset += 4;
727 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_b, tvb, offset, 4, ENC_BIG_ENDIAN);
728 	offset += 4;
729 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_b, tvb, offset, 4, ENC_BIG_ENDIAN);
730 	offset += 4;
731 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_c, tvb, offset, 4, ENC_BIG_ENDIAN);
732 	offset += 4;
733 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_c, tvb, offset, 4, ENC_BIG_ENDIAN);
734 	offset += 4;
735 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lat_d, tvb, offset, 4, ENC_BIG_ENDIAN);
736 	offset += 4;
737 	proto_tree_add_item(seg_tree, hf_4607_jobdef_ba_lon_d, tvb, offset, 4, ENC_BIG_ENDIAN);
738 	offset += 4;
739 	proto_tree_add_item(seg_tree, hf_4607_jobdef_radar_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
740 	offset += 1;
741 	proto_tree_add_item(seg_tree, hf_4607_jobdef_revisit_interval, tvb, offset, 2, ENC_BIG_ENDIAN);
742 	offset += 2;
743 	proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_along, tvb, offset, 2, ENC_BIG_ENDIAN);
744 	offset += 2;
745 	proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_cross, tvb, offset, 2, ENC_BIG_ENDIAN);
746 	offset += 2;
747 	proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_alt, tvb, offset, 2, ENC_BIG_ENDIAN);
748 	offset += 2;
749 	proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_heading, tvb, offset, 1, ENC_BIG_ENDIAN);
750 	offset += 1;
751 	proto_tree_add_item(seg_tree, hf_4607_jobdef_unc_speed, tvb, offset, 2, ENC_BIG_ENDIAN);
752 	offset += 2;
753 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_slant, tvb, offset, 2, ENC_BIG_ENDIAN);
754 	offset += 2;
755 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_cross, tvb, offset, 2, ENC_BIG_ENDIAN);
756 	offset += 2;
757 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_vlos, tvb, offset, 2, ENC_BIG_ENDIAN);
758 	offset += 2;
759 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_mdv, tvb, offset, 1, ENC_BIG_ENDIAN);
760 	offset += 1;
761 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_prob, tvb, offset, 1, ENC_BIG_ENDIAN);
762 	offset += 1;
763 	proto_tree_add_item(seg_tree, hf_4607_jobdef_sense_alarm, tvb, offset, 1, ENC_BIG_ENDIAN);
764 	offset += 1;
765 	proto_tree_add_item(seg_tree, hf_4607_jobdef_terrain_model, tvb, offset, 1, ENC_BIG_ENDIAN);
766 	offset += 1;
767 	proto_tree_add_item(seg_tree, hf_4607_jobdef_geoid_model, tvb, offset, 1, ENC_BIG_ENDIAN);
768 	offset += 1;
769 
770 	return offset;
771 }
772 
773 static gint
dissect_platform_location(tvbuff_t * tvb,proto_tree * seg_tree,gint offset)774 dissect_platform_location(tvbuff_t *tvb, proto_tree *seg_tree, gint offset)
775 {
776 	proto_tree_add_item(seg_tree, hf_4607_platloc_time, tvb, offset, 4, ENC_BIG_ENDIAN);
777 	offset += 4;
778 	proto_tree_add_item(seg_tree, hf_4607_platloc_latitude, tvb, offset, 4, ENC_BIG_ENDIAN);
779 	offset += 4;
780 	proto_tree_add_item(seg_tree, hf_4607_platloc_longitude, tvb, offset, 4, ENC_BIG_ENDIAN);
781 	offset += 4;
782 	proto_tree_add_item(seg_tree, hf_4607_platloc_altitude, tvb, offset, 4, ENC_BIG_ENDIAN);
783 	offset += 4;
784 	proto_tree_add_item(seg_tree, hf_4607_platloc_track, tvb, offset, 2, ENC_BIG_ENDIAN);
785 	offset += 2;
786 	proto_tree_add_item(seg_tree, hf_4607_platloc_speed, tvb, offset, 4, ENC_BIG_ENDIAN);
787 	offset += 4;
788 	proto_tree_add_item(seg_tree, hf_4607_platloc_vertical_velocity, tvb, offset, 1, ENC_BIG_ENDIAN);
789 	offset += 1;
790 	return offset;
791 }
792 
793 /* 32 == packet header, 5 == segment type and length */
794 #define STANAG4607_MIN_LENGTH (32+5)
795 
796 #define MINIMUM_SEGMENT_SIZE 14
797 #define MISSION_SEGMENT_SIZE 44
798 #define JOB_DEFINITION_SEGMENT_SIZE 73
799 #define PLATFORM_LOCATION_SEGMENT_SIZE 28
800 
801 /* Provide a basic sanity check on segment sizes; the fixed-length
802  * ones should be what they claim to be.
803  */
804 #define CHK_SIZE(SEG_TYPE) \
805 	if (SEG_TYPE##_SIZE != seg_size) { \
806 		col_append_str(pinfo->cinfo, COL_INFO, ", Error: Invalid segment size "); \
807 		expert_add_info(pinfo, pi, &ei_bad_length); \
808 	}
809 
810 static int
dissect_stanag4607(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)811 dissect_stanag4607(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
812 {
813 	guint32 offset = 0;
814 	gint8 first_segment;
815 
816 	guint32 pkt_size = 0;
817 	proto_item *ti = NULL;
818 	proto_tree *hdr_tree = NULL;
819 	proto_item *seg_type = NULL;
820 	proto_tree *seg_tree = NULL;
821 	guint8 seg_id = 0;
822 
823 	/* Basic length check */
824 	if (tvb_captured_length(tvb) < STANAG4607_MIN_LENGTH)
825 		return 0;
826 
827 	col_set_str(pinfo->cinfo, COL_PROTOCOL, "S4607");
828 	/* Clear out stuff in the info column */
829 	col_clear(pinfo->cinfo, COL_INFO);
830 
831 	/* Put type of first segment in the info column */
832 	first_segment = tvb_get_guint8(tvb, 32);
833 	col_add_str(pinfo->cinfo, COL_INFO,
834 			val_to_str(first_segment, stanag4607_segment_vals, "Unknown (0x%02x)"));
835 
836 	/* Put the timestamp, if available in the time column */
837 	if (PLATFORM_LOCATION_SEGMENT == first_segment) {
838 		guint32 millisecs;
839 		nstime_t ts;
840 		millisecs = tvb_get_ntohl(tvb, 37);
841 		ts.secs = millisecs / 1000;
842 		ts.nsecs = (int)((millisecs - 1000 * ts.secs) * 1000000);
843 		col_set_time(pinfo->cinfo, COL_REL_TIME, &ts, "s4607.ploc.time");
844 	}
845 
846 	/* The generic packet header */
847 	if (tree) {
848 		ti = proto_tree_add_item(tree, proto_stanag4607, tvb, 0, -1, ENC_NA);
849 		hdr_tree = proto_item_add_subtree(ti, ett_4607_hdr);
850 		proto_tree_add_item(hdr_tree, hf_4607_version, tvb, 0, 2, ENC_ASCII|ENC_NA);
851 		ti = proto_tree_add_item(hdr_tree, hf_4607_packet_size, tvb, 2, 4, ENC_BIG_ENDIAN);
852 		proto_tree_add_item(hdr_tree, hf_4607_nationality, tvb, 6, 2, ENC_ASCII|ENC_NA);
853 		proto_tree_add_item(hdr_tree, hf_4607_sec_class, tvb, 8, 1, ENC_BIG_ENDIAN);
854 		proto_tree_add_item(hdr_tree, hf_4607_sec_system, tvb, 9, 2, ENC_ASCII|ENC_NA);
855 		proto_tree_add_item(hdr_tree, hf_4607_sec_code, tvb, 11, 2, ENC_BIG_ENDIAN);
856 		proto_tree_add_item(hdr_tree, hf_4607_exercise_indicator, tvb, 13, 1, ENC_BIG_ENDIAN);
857 		proto_tree_add_item(hdr_tree, hf_4607_platform_id, tvb, 14, 10, ENC_ASCII|ENC_NA);
858 		proto_tree_add_item(hdr_tree, hf_4607_mission_id, tvb, 24, 4, ENC_BIG_ENDIAN);
859 		proto_tree_add_item(hdr_tree, hf_4607_job_id, tvb, 28, 4, ENC_BIG_ENDIAN);
860 	}
861 	offset = 32;
862 
863 	pkt_size = tvb_get_ntohl(tvb, 2);
864 
865 	/* Ruh ro. These should be equal... */
866 	if (tvb_reported_length(tvb) != pkt_size) {
867 		expert_add_info(pinfo, ti, &ei_bad_packet_size);
868 		pkt_size = tvb_reported_length(tvb);
869 	}
870 
871 	/* Loop over all segments in the packet */
872 	while (offset < pkt_size) {
873 		guint32 seg_size = 0;
874 		guint32 saved_offset = offset;
875 
876 		proto_item * pi;
877 		/* Segment header */
878 		seg_type = proto_tree_add_item(hdr_tree, hf_4607_segment_type, tvb, offset, 1, ENC_BIG_ENDIAN);
879 		seg_id = tvb_get_guint8(tvb, offset);
880 		offset += 1;
881 
882 		seg_tree = proto_item_add_subtree(seg_type, ett_4607_seg);
883 		pi = proto_tree_add_item(seg_tree, hf_4607_segment_size, tvb, offset, 4, ENC_BIG_ENDIAN);
884 		seg_size = tvb_get_ntohl(tvb, offset);
885 		offset += 4;
886 		if (seg_size < MINIMUM_SEGMENT_SIZE) {
887 			seg_size = MINIMUM_SEGMENT_SIZE;
888 			col_append_str(pinfo->cinfo, COL_INFO, ", Error: Invalid segment size ");
889 			expert_add_info(pinfo, pi, &ei_too_short);
890 		}
891 
892 		switch (seg_id) {
893 			case MISSION_SEGMENT:
894 				CHK_SIZE(MISSION_SEGMENT);
895 				offset = dissect_mission(tvb, seg_tree, offset);
896 				break;
897 			case DWELL_SEGMENT:
898 				offset = dissect_dwell(tvb, seg_tree, offset);
899 				break;
900 			case JOB_DEFINITION_SEGMENT:
901 				CHK_SIZE(JOB_DEFINITION_SEGMENT);
902 				offset = dissect_jobdef(tvb, seg_tree, offset);
903 				break;
904 			case PLATFORM_LOCATION_SEGMENT:
905 				CHK_SIZE(PLATFORM_LOCATION_SEGMENT);
906 				offset = dissect_platform_location(tvb, seg_tree, offset);
907 				break;
908 			default:
909 				offset += seg_size - 5;
910 				break;
911 		}
912 
913 		if (offset < saved_offset) {
914 			/* overflow */
915 			break;
916 		}
917 	}
918 	return tvb_captured_length(tvb);
919 }
920 
921 void
proto_register_stanag4607(void)922 proto_register_stanag4607(void)
923 {
924 	static hf_register_info hf[] = {
925 		/* ========================================== */
926 		/* Packet header */
927 		{ &hf_4607_version,
928 			{ "Version ID", "s4607.version",
929 			FT_STRING, BASE_NONE,
930 			NULL, 0x0,
931 			NULL, HFILL }
932 		},
933 		{ &hf_4607_packet_size,
934 			{ "Packet Size", "s4607.size",
935 			FT_UINT32, BASE_DEC,
936 			NULL, 0x0,
937 			NULL, HFILL }
938 		},
939 		{ &hf_4607_nationality,
940 			{ "Nationality", "s4607.nationality",
941 			FT_STRING, BASE_NONE,
942 			NULL, 0x0,
943 			NULL, HFILL }
944 		},
945 		{ &hf_4607_sec_class,
946 			{ "Security Classification", "s4607.sec.class",
947 			FT_UINT8, BASE_DEC,
948 			VALS(stanag4607_class_vals), 0x0,
949 			NULL, HFILL }
950 		},
951 		{ &hf_4607_sec_system,
952 			{ "Security System", "s4607.sec.system",
953 			FT_STRING, BASE_NONE,
954 			NULL, 0x0,
955 			NULL, HFILL }
956 		},
957 		{ &hf_4607_sec_code,
958 			{ "Security Codes", "s4607.sec.codes",
959 			FT_UINT16, BASE_HEX,
960 			NULL, 0x0,
961 			NULL, HFILL }
962 		},
963 		{ &hf_4607_exercise_indicator,
964 			{ "Exercise Indicator", "s4607.exind",
965 			FT_UINT8, BASE_DEC,
966 			VALS(stanag4607_exind_vals), 0x0,
967 			NULL, HFILL }
968 		},
969 		{ &hf_4607_platform_id,
970 			{ "Platform ID", "s4607.platform",
971 			FT_STRING, BASE_NONE,
972 			NULL, 0x0,
973 			NULL, HFILL }
974 		},
975 		{ &hf_4607_mission_id,
976 			{ "Mission ID", "s4607.mission",
977 			FT_UINT32, BASE_DEC,
978 			NULL, 0x0,
979 			NULL, HFILL }
980 		},
981 		{ &hf_4607_job_id,
982 			{ "Job ID", "s4607.job",
983 			FT_UINT32, BASE_DEC,
984 			NULL, 0x0,
985 			NULL, HFILL }
986 		},
987 
988 		/* ========================================== */
989 		/* Segment header */
990 		{ &hf_4607_segment_type,
991 			{ "Segment Type", "s4607.seg.type",
992 			FT_UINT8, BASE_DEC,
993 			VALS(stanag4607_segment_vals), 0x0,
994 			NULL, HFILL }
995 		},
996 		{ &hf_4607_segment_size,
997 			{ "Segment Size", "s4607.seg.size",
998 			FT_UINT32, BASE_DEC,
999 			NULL, 0x0,
1000 			NULL, HFILL }
1001 		},
1002 
1003 		/* ========================================== */
1004 		/* Dwell Segment */
1005 		{ &hf_4607_dwell_mask,
1006 			{ "Existence Mask", "s4607.dwell.mask",
1007 			FT_UINT64, BASE_HEX,
1008 			NULL, 0x0,
1009 			NULL, HFILL }
1010 		},
1011 		{ &hf_4607_dwell_revisit_index,
1012 			{ "Revisit Index", "s4607.dwell.revisit",
1013 			FT_UINT16, BASE_DEC,
1014 			NULL, 0x0,
1015 			NULL, HFILL }
1016 		},
1017 		{ &hf_4607_dwell_dwell_index,
1018 			{ "Dwell Index", "s4607.dwell.dwell",
1019 			FT_UINT16, BASE_DEC,
1020 			NULL, 0x0,
1021 			NULL, HFILL }
1022 		},
1023 		{ &hf_4607_dwell_last_dwell,
1024 			{ "Last Dwell of Revisit", "s4607.dwell.last",
1025 			FT_UINT8, BASE_DEC,
1026 			NULL, 0x0,
1027 			NULL, HFILL }
1028 		},
1029 		{ &hf_4607_dwell_count,
1030 			{ "Target Report Count", "s4607.dwell.count",
1031 			FT_UINT16, BASE_DEC,
1032 			NULL, 0x0,
1033 			NULL, HFILL }
1034 		},
1035 		{ &hf_4607_dwell_time,
1036 			{ "Dwell Time", "s4607.dwell.time",
1037 			FT_UINT32, BASE_CUSTOM,
1038 			CF_FUNC(prt_millisec), 0x0,
1039 			NULL, HFILL }
1040 		},
1041 		{ &hf_4607_dwell_sensor_lat,
1042 			{ "Sensor Position Latitude", "s4607.dwell.sensor.lat",
1043 			FT_INT32, BASE_CUSTOM,
1044 			CF_FUNC(prt_sa32), 0x0,
1045 			NULL, HFILL }
1046 		},
1047 		{ &hf_4607_dwell_sensor_lon,
1048 			{ "Sensor Position Longitude", "s4607.dwell.sensor.lon",
1049 			FT_UINT32, BASE_CUSTOM,
1050 			CF_FUNC(prt_ba32), 0x0,
1051 			NULL, HFILL }
1052 		},
1053 		{ &hf_4607_dwell_sensor_alt,
1054 			{ "Sensor Position Altitude", "s4607.dwell.sensor.alt",
1055 			FT_INT32, BASE_CUSTOM,
1056 			CF_FUNC(prt_centimeters), 0x0,
1057 			NULL, HFILL }
1058 		},
1059 		/* D10 */
1060 		{ &hf_4607_dwell_scale_lat,
1061 			{ "Scale Factor, Latitude", "s4607.dwell.scale.lat",
1062 			FT_INT32, BASE_CUSTOM,
1063 			CF_FUNC(prt_sa32), 0x0,
1064 			NULL, HFILL }
1065 		},
1066 		{ &hf_4607_dwell_scale_lon,
1067 			{ "Scale Factor, Longitude", "s4607.dwell.scale.lon",
1068 			FT_UINT32, BASE_CUSTOM,
1069 			CF_FUNC(prt_ba32), 0x0,
1070 			NULL, HFILL }
1071 		},
1072 
1073 		/* D12 */
1074 		{ &hf_4607_dwell_unc_along,
1075 			{ "Sensor Position Uncertainty Along Track", "s4607.dwell.unc.along",
1076 			FT_UINT32, BASE_CUSTOM,
1077 			CF_FUNC(prt_centimeters), 0x0,
1078 			NULL, HFILL }
1079 		},
1080 		{ &hf_4607_dwell_unc_cross,
1081 			{ "Sensor Position Uncertainty Cross Track", "s4607.dwell.unc.cross",
1082 			FT_UINT32, BASE_CUSTOM,
1083 			CF_FUNC(prt_centimeters), 0x0,
1084 			NULL, HFILL }
1085 		},
1086 		{ &hf_4607_dwell_unc_alt,
1087 			{ "Sensor Position Uncertainty Altitude", "s4607.dwell.unc.alt",
1088 			FT_UINT16, BASE_CUSTOM,
1089 			CF_FUNC(prt_centimeters), 0x0,
1090 			NULL, HFILL }
1091 		},
1092 
1093 		/* D15 */
1094 		{ &hf_4607_dwell_track,
1095 			{ "Sensor Track", "s4607.dwell.track",
1096 			FT_UINT16, BASE_CUSTOM,
1097 			CF_FUNC(prt_ba16), 0x0,
1098 			NULL, HFILL }
1099 		},
1100 		{ &hf_4607_dwell_speed,
1101 			{ "Sensor Speed", "s4607.dwell.speed",
1102 			FT_UINT32, BASE_CUSTOM,
1103 			CF_FUNC(prt_speed), 0x0,
1104 			NULL, HFILL }
1105 		},
1106 		{ &hf_4607_dwell_vert_velocity,
1107 			{ "Sensor Vertical Velocity", "s4607.dwell.vvel",
1108 			FT_INT8, BASE_CUSTOM,
1109 			CF_FUNC(prt_speed_deci), 0x0,
1110 			NULL, HFILL }
1111 		},
1112 		{ &hf_4607_dwell_track_unc,
1113 			{ "Sensor Track Uncertainty", "s4607.dwell.track.unc",
1114 			FT_UINT8, BASE_DEC,
1115 			NULL, 0x0,
1116 			NULL, HFILL }
1117 		},
1118 		{ &hf_4607_dwell_speed_unc,
1119 			{ "Sensor Speed Uncertainty", "s4607.dwell.speed.unc",
1120 			FT_UINT16, BASE_CUSTOM,
1121 			CF_FUNC(prt_speed), 0x0,
1122 			NULL, HFILL }
1123 		},
1124 		{ &hf_4607_dwell_vv_unc,
1125 			{ "Sensor Vertical Velocity Uncertainty", "s4607.dwell.vvel.unc",
1126 			FT_UINT16, BASE_CUSTOM,
1127 			CF_FUNC(prt_speed_centi), 0x0,
1128 			NULL, HFILL }
1129 		},
1130 
1131 		/* D21 */
1132 		{ &hf_4607_dwell_plat_heading,
1133 			{ "Platform Orientation Heading", "s4607.dwell.plat.heading",
1134 			FT_UINT16, BASE_CUSTOM,
1135 			CF_FUNC(prt_ba16), 0x0,
1136 			NULL, HFILL }
1137 		},
1138 		{ &hf_4607_dwell_plat_pitch,
1139 			{ "Platform Orientation Pitch", "s4607.dwell.plat.pitch",
1140 			FT_INT16, BASE_CUSTOM,
1141 			CF_FUNC(prt_sa16), 0x0,
1142 			NULL, HFILL }
1143 		},
1144 		{ &hf_4607_dwell_plat_roll,
1145 			{ "Platform Orientation Roll (Bank Angle)", "s4607.dwell.plat.roll",
1146 			FT_INT16, BASE_CUSTOM,
1147 			CF_FUNC(prt_sa16), 0x0,
1148 			NULL, HFILL }
1149 		},
1150 
1151 		/* D24 */
1152 		{ &hf_4607_dwell_da_lat,
1153 			{ "Dwell Area Center Latitude", "s4607.dwell.da.lat",
1154 			FT_INT32, BASE_CUSTOM,
1155 			CF_FUNC(prt_sa32), 0x0,
1156 			NULL, HFILL }
1157 		},
1158 		{ &hf_4607_dwell_da_lon,
1159 			{ "Dwell Area Center Longitude", "s4607.dwell.da.lon",
1160 			FT_UINT32, BASE_CUSTOM,
1161 			CF_FUNC(prt_ba32), 0x0,
1162 			NULL, HFILL }
1163 		},
1164 		{ &hf_4607_dwell_da_range,
1165 			{ "Dwell Area Range Half Extent", "s4607.dwell.da.range",
1166 			FT_UINT16, BASE_CUSTOM,
1167 			CF_FUNC(prt_kilo), 0x0,
1168 			NULL, HFILL }
1169 		},
1170 		{ &hf_4607_dwell_da_angle,
1171 			{ "Dwell Area Dwell Angle Half Extent", "s4607.dwell.da.angle",
1172 			FT_UINT16, BASE_CUSTOM,
1173 			CF_FUNC(prt_ba16), 0x0,
1174 			NULL, HFILL }
1175 		},
1176 
1177 		/* D28 */
1178 		{ &hf_4607_dwell_sensor_heading,
1179 			{ "Sensor Orientation Heading", "s4607.dwell.sensor.heading",
1180 			FT_UINT16, BASE_CUSTOM,
1181 			CF_FUNC(prt_ba16), 0x0,
1182 			NULL, HFILL }
1183 		},
1184 		{ &hf_4607_dwell_sensor_pitch,
1185 			{ "Sensor Orientation Pitch", "s4607.dwell.sensor.pitch",
1186 			FT_INT16, BASE_CUSTOM,
1187 			CF_FUNC(prt_sa16), 0x0,
1188 			NULL, HFILL }
1189 		},
1190 		{ &hf_4607_dwell_sensor_roll,
1191 			{ "Sensor Orientation Roll (Bank Angle)", "s4607.dwell.sensor.roll",
1192 			FT_INT16, BASE_CUSTOM,
1193 			CF_FUNC(prt_sa16), 0x0,
1194 			NULL, HFILL }
1195 		},
1196 		{ &hf_4607_dwell_mdv,
1197 			{ "Minimum Detectable Velocity (MDV)", "s4607.dwell.mdv",
1198 			FT_UINT8, BASE_CUSTOM,
1199 			CF_FUNC(prt_speed_deci), 0x0,
1200 			NULL, HFILL }
1201 		},
1202 
1203 		/* ========================================== */
1204 		/* Target Report */
1205 		{ &hf_4607_dwell_report_index,
1206 			{ "MTI Report Index", "s4607.dwell.rpt.idx",
1207 			FT_UINT16, BASE_DEC,
1208 			NULL, 0x0,
1209 			NULL, HFILL }
1210 		},
1211 
1212 		/* D32.2 */
1213 		{ &hf_4607_dwell_report_lat,
1214 			{ "Target Location Hi-Res Latitude", "s4607.dwell.rpt.lat",
1215 			FT_INT32, BASE_CUSTOM,
1216 			CF_FUNC(prt_sa32), 0x0,
1217 			NULL, HFILL }
1218 		},
1219 		{ &hf_4607_dwell_report_lon,
1220 			{ "Target Location Hi-Res Longitude", "s4607.dwell.rpt.lon",
1221 			FT_UINT32, BASE_CUSTOM,
1222 			CF_FUNC(prt_ba32), 0x0,
1223 			NULL, HFILL }
1224 		},
1225 
1226 		/* D32.4 */
1227 		{ &hf_4607_dwell_report_delta_lat,
1228 			{ "Target Location Delta Latitude", "s4607.dwell.rpt.delta.lat",
1229 			FT_INT16, BASE_DEC,
1230 			NULL, 0x0,
1231 			NULL, HFILL }
1232 		},
1233 		{ &hf_4607_dwell_report_delta_lon,
1234 			{ "Target Location Delta Longitude", "s4607.dwell.rpt.delta.lon",
1235 			FT_INT16, BASE_DEC,
1236 			NULL, 0x0,
1237 			NULL, HFILL }
1238 		},
1239 
1240 		/* D32.6 */
1241 		{ &hf_4607_dwell_report_height,
1242 			{ "Target Location Geodetic Height", "s4607.dwell.rpt.height",
1243 			FT_INT16, BASE_CUSTOM,
1244 			CF_FUNC(prt_meters), 0x0,
1245 			NULL, HFILL }
1246 		},
1247 
1248 		/* D32.7 */
1249 		{ &hf_4607_dwell_report_radial,
1250 			{ "Target Velocity Line of Sight Component", "s4607.dwell.rpt.radial",
1251 			FT_INT16, BASE_CUSTOM,
1252 			CF_FUNC(prt_speed_centi), 0x0,
1253 			NULL, HFILL }
1254 		},
1255 		{ &hf_4607_dwell_report_wrap,
1256 			{ "Target Wrap Velocity", "s4607.dwell.rpt.wrap",
1257 			FT_UINT16, BASE_CUSTOM,
1258 			CF_FUNC(prt_speed_centi), 0x0,
1259 			NULL, HFILL }
1260 		},
1261 		{ &hf_4607_dwell_report_snr,
1262 			{ "Target SNR", "s4607.dwell.rpt.snr",
1263 			FT_INT8, BASE_DEC,
1264 			NULL, 0x0,
1265 			NULL, HFILL }
1266 		},
1267 		{ &hf_4607_dwell_report_class,
1268 			{ "Target Classification", "s4607.dwell.rpt.class",
1269 			FT_UINT8, BASE_DEC,
1270 			VALS(stanag4607_target_vals), 0x0,
1271 			NULL, HFILL }
1272 		},
1273 		{ &hf_4607_dwell_report_prob,
1274 			{ "Target Class Probability", "s4607.dwell.rpt.prob",
1275 			FT_UINT8, BASE_DEC,
1276 			NULL, 0x0,
1277 			NULL, HFILL }
1278 		},
1279 
1280 		/* D32.12 */
1281 		{ &hf_4607_dwell_report_unc_slant,
1282 			{ "Target Measurement Uncertainty Slant Range", "s4607.dwell.rpt.unc.slant",
1283 			FT_UINT16, BASE_CUSTOM,
1284 			CF_FUNC(prt_centimeters), 0x0,
1285 			NULL, HFILL }
1286 		},
1287 		{ &hf_4607_dwell_report_unc_cross,
1288 			{ "Target Measurement Uncertainty Cross Range", "s4607.dwell.rpt.unc.cross",
1289 			FT_UINT16, BASE_CUSTOM,
1290 			CF_FUNC(prt_decimeters), 0x0,
1291 			NULL, HFILL }
1292 		},
1293 		{ &hf_4607_dwell_report_unc_height,
1294 			{ "Target Measurement Uncertainty Height", "s4607.dwell.rpt.unc.height",
1295 			FT_UINT8, BASE_CUSTOM,
1296 			CF_FUNC(prt_meters), 0x0,
1297 			NULL, HFILL }
1298 		},
1299 		{ &hf_4607_dwell_report_unc_radial,
1300 			{ "Target Measurement Uncertainty Radial Velocity", "s4607.dwell.rpt.unc.radial",
1301 			FT_UINT16, BASE_CUSTOM,
1302 			CF_FUNC(prt_speed_centi), 0x0,
1303 			NULL, HFILL }
1304 		},
1305 
1306 		/* D32.16 */
1307 		{ &hf_4607_dwell_report_tag_app,
1308 			{ "Truth Tag Application", "s4607.dwell.rpt.tag.app",
1309 			FT_UINT8, BASE_DEC,
1310 			NULL, 0x0,
1311 			NULL, HFILL }
1312 		},
1313 		{ &hf_4607_dwell_report_tag_entity,
1314 			{ "Truth Tag Entity", "s4607.dwell.rpt.tag.entity",
1315 			FT_UINT32, BASE_DEC,
1316 			NULL, 0x0,
1317 			NULL, HFILL }
1318 		},
1319 		{ &hf_4607_dwell_report_section,
1320 			{ "Radar Cross Section", "s4607.dwell.rpt.section",
1321 			FT_INT8, BASE_DEC,
1322 			NULL, 0x0,
1323 			NULL, HFILL }
1324 		},
1325 
1326 
1327 		/* ========================================== */
1328 		/* Job Definition Segment */
1329 		{ &hf_4607_jobdef_job_id,
1330 			{ "Job ID", "s4607.job.id",
1331 			FT_UINT32, BASE_DEC,
1332 			NULL, 0x0,
1333 			NULL, HFILL }
1334 		},
1335 		{ &hf_4607_jobdef_sensor_type,
1336 			{ "Sensor Type", "s4607.job.type",
1337 			FT_UINT8, BASE_DEC,
1338 			VALS(stanag4607_sensor_vals), 0x0,
1339 			NULL, HFILL }
1340 		},
1341 		{ &hf_4607_jobdef_sensor_model,
1342 			{ "Sensor Model", "s4607.job.model",
1343 			FT_STRING, BASE_NONE,
1344 			NULL, 0x0,
1345 			NULL, HFILL }
1346 		},
1347 		{ &hf_4607_jobdef_filter,
1348 			{ "Target Filtering Flag", "s4607.job.filter",
1349 			FT_UINT8, BASE_DEC,
1350 			NULL, 0x0,
1351 			NULL, HFILL }
1352 		},
1353 		{ &hf_4607_jobdef_priority,
1354 			{ "Radar Priority", "s4607.job.priority",
1355 			FT_UINT8, BASE_DEC,
1356 			NULL, 0x0,
1357 			NULL, HFILL }
1358 		},
1359 
1360 		{ &hf_4607_jobdef_ba_lat_a,
1361 			{ "Bounding Area Point A Latitude", "s4607.job.ba.lat.a",
1362 			FT_INT32, BASE_CUSTOM,
1363 			CF_FUNC(prt_sa32), 0x0,
1364 			NULL, HFILL }
1365 		},
1366 		{ &hf_4607_jobdef_ba_lon_a,
1367 			{ "Bounding Area Point A Longitude", "s4607.job.ba.lon.a",
1368 			FT_UINT32, BASE_CUSTOM,
1369 			CF_FUNC(prt_ba32), 0x0,
1370 			NULL, HFILL }
1371 		},
1372 
1373 		{ &hf_4607_jobdef_ba_lat_b,
1374 			{ "Bounding Area Point B Latitude", "s4607.job.ba.lat.b",
1375 			FT_INT32, BASE_CUSTOM,
1376 			CF_FUNC(prt_sa32), 0x0,
1377 			NULL, HFILL }
1378 		},
1379 		{ &hf_4607_jobdef_ba_lon_b,
1380 			{ "Bounding Area Point B Longitude", "s4607.job.ba.lon.b",
1381 			FT_UINT32, BASE_CUSTOM,
1382 			CF_FUNC(prt_ba32), 0x0,
1383 			NULL, HFILL }
1384 		},
1385 		{ &hf_4607_jobdef_ba_lat_c,
1386 			{ "Bounding Area Point C Latitude", "s4607.job.ba.lat.c",
1387 			FT_INT32, BASE_CUSTOM,
1388 			CF_FUNC(prt_sa32), 0x0,
1389 			NULL, HFILL }
1390 		},
1391 		{ &hf_4607_jobdef_ba_lon_c,
1392 			{ "Bounding Area Point C Longitude", "s4607.job.ba.lon.c",
1393 			FT_UINT32, BASE_CUSTOM,
1394 			CF_FUNC(prt_ba32), 0x0,
1395 			NULL, HFILL }
1396 		},
1397 		{ &hf_4607_jobdef_ba_lat_d,
1398 			{ "Bounding Area Point D Latitude", "s4607.job.ba.lat.d",
1399 			FT_INT32, BASE_CUSTOM,
1400 			CF_FUNC(prt_sa32), 0x0,
1401 			NULL, HFILL }
1402 		},
1403 		{ &hf_4607_jobdef_ba_lon_d,
1404 			{ "Bounding Area Point D Longitude", "s4607.job.ba.lon.d",
1405 			FT_UINT32, BASE_CUSTOM,
1406 			CF_FUNC(prt_ba32), 0x0,
1407 			NULL, HFILL }
1408 		},
1409 
1410 		{ &hf_4607_jobdef_radar_mode,
1411 			{ "Radar Mode", "s4607.job.mode",
1412 			FT_UINT8, BASE_DEC,
1413 			VALS(stanag4607_radar_mode_vals), 0x0,
1414 			NULL, HFILL }
1415 		},
1416 
1417 		{ &hf_4607_jobdef_revisit_interval,
1418 			{ "Nominal Revisit Interval", "s4607.job.revisit",
1419 			FT_UINT16, BASE_DEC,
1420 			NULL, 0x0,
1421 			NULL, HFILL }
1422 		},
1423 		{ &hf_4607_jobdef_unc_along,
1424 			{ "Nominal Sensor Position Uncertainty Along Track", "s4607.job.unc.track",
1425 			FT_UINT16, BASE_CUSTOM,
1426 			CF_FUNC(prt_none16), 0x0,
1427 			NULL, HFILL }
1428 		},
1429 		{ &hf_4607_jobdef_unc_cross,
1430 			{ "Nominal Sensor Position Uncertainty Cross Track", "s4607.job.unc.cross",
1431 			FT_UINT16, BASE_CUSTOM,
1432 			CF_FUNC(prt_none16), 0x0,
1433 			NULL, HFILL }
1434 		},
1435 		{ &hf_4607_jobdef_unc_alt,
1436 			{ "Nominal Sensor Position Uncertainty Altitude", "s4607.job.unc.alt",
1437 			FT_UINT16, BASE_CUSTOM,
1438 			CF_FUNC(prt_none16), 0x0,
1439 			NULL, HFILL }
1440 		},
1441 		{ &hf_4607_jobdef_unc_heading,
1442 			{ "Nominal Sensor Position Uncertainty Track Heading", "s4607.job.unc.heading",
1443 			FT_UINT8, BASE_CUSTOM,
1444 			CF_FUNC(prt_none8), 0x0,
1445 			NULL, HFILL }
1446 		},
1447 		{ &hf_4607_jobdef_unc_speed,
1448 			{ "Nominal Sensor Position Uncertainty Speed", "s4607.job.unc.speed",
1449 			FT_UINT16, BASE_CUSTOM,
1450 			CF_FUNC(prt_none16), 0x0,
1451 			NULL, HFILL }
1452 		},
1453 
1454 		{ &hf_4607_jobdef_sense_slant,
1455 			{ "Nominal Sensor Slant Range Standard Deviation", "s4607.job.sense.slant",
1456 			FT_UINT16, BASE_CUSTOM,
1457 			CF_FUNC(prt_none16), 0x0,
1458 			NULL, HFILL }
1459 		},
1460 		{ &hf_4607_jobdef_sense_cross,
1461 			{ "Nominal Sensor Cross Range Standard Deviation", "s4607.job.sense.cross",
1462 			FT_UINT16, BASE_CUSTOM,
1463 			CF_FUNC(prt_ba16_none), 0x0,
1464 			NULL, HFILL }
1465 		},
1466 		{ &hf_4607_jobdef_sense_vlos,
1467 			{ "Nominal Sensor Velocity Line-Of-Sight Std. Dev", "s4607.job.sense.vlos",
1468 			FT_UINT16, BASE_CUSTOM,
1469 			CF_FUNC(prt_none16), 0x0,
1470 			NULL, HFILL }
1471 		},
1472 		{ &hf_4607_jobdef_sense_mdv,
1473 			{ "Nominal Sensor Minimum Detectable Velocity (MDV)", "s4607.job.sense.mdv",
1474 			FT_UINT8, BASE_CUSTOM,
1475 			CF_FUNC(prt_none8), 0x0,
1476 			NULL, HFILL }
1477 		},
1478 		{ &hf_4607_jobdef_sense_prob,
1479 			{ "Nominal Sensor Detection Probability", "s4607.job.sense.prob",
1480 			FT_UINT8, BASE_CUSTOM,
1481 			CF_FUNC(prt_none8), 0x0,
1482 			NULL, HFILL }
1483 		},
1484 		{ &hf_4607_jobdef_sense_alarm,
1485 			{ "Nominal Sensor False Alarm Density", "s4607.job.sense.alarm",
1486 			FT_UINT8, BASE_CUSTOM,
1487 			CF_FUNC(prt_none8), 0x0,
1488 			NULL, HFILL }
1489 		},
1490 		{ &hf_4607_jobdef_terrain_model,
1491 			{ "Terrain Elevation Model Used", "s4607.job.terrain",
1492 			FT_UINT8, BASE_DEC,
1493 			VALS(stanag4607_terrain_vals), 0x0,
1494 			NULL, HFILL }
1495 		},
1496 		{ &hf_4607_jobdef_geoid_model,
1497 			{ "Geoid Model Used", "s4607.job.geoid",
1498 			FT_UINT8, BASE_DEC,
1499 			VALS(stanag4607_geoid_vals), 0x0,
1500 			NULL, HFILL }
1501 		},
1502 
1503 
1504 		/* ========================================== */
1505 		/* Mission segment */
1506 		{ &hf_4607_mission_plan,
1507 			{ "Mission Plan", "s4607.mission.plan",
1508 			FT_STRING, BASE_NONE,
1509 			NULL, 0x0,
1510 			NULL, HFILL }
1511 		},
1512 		{ &hf_4607_mission_flight_plan,
1513 			{ "Mission Flight Plan", "s4607.mission.flight",
1514 			FT_STRING, BASE_NONE,
1515 			NULL, 0x0,
1516 			NULL, HFILL }
1517 		},
1518 		{ &hf_4607_mission_platform,
1519 			{ "Mission Platform Type", "s4607.mission.platform",
1520 			FT_UINT8, BASE_DEC,
1521 			VALS(stanag4607_platform_vals), 0x0,
1522 			NULL, HFILL }
1523 		},
1524 		{ &hf_4607_mission_platform_config,
1525 			{ "Mission Platform Configuration", "s4607.mission.config",
1526 			FT_STRING, BASE_NONE,
1527 			NULL, 0x0,
1528 			NULL, HFILL }
1529 		},
1530 		{ &hf_4607_mission_time_year,
1531 			{ "Mission Reference Time Year", "s4607.mission.year",
1532 			FT_UINT16, BASE_DEC,
1533 			NULL, 0x0,
1534 			NULL, HFILL }
1535 		},
1536 		{ &hf_4607_mission_time_month,
1537 			{ "Mission Reference Time Month", "s4607.mission.month",
1538 			FT_UINT8, BASE_DEC,
1539 			NULL, 0x0,
1540 			NULL, HFILL }
1541 		},
1542 		{ &hf_4607_mission_time_day,
1543 			{ "Mission Reference Time Day", "s4607.mission.day",
1544 			FT_UINT8, BASE_DEC,
1545 			NULL, 0x0,
1546 			NULL, HFILL }
1547 		},
1548 		/* ========================================== */
1549 		{ &hf_4607_platloc_time,
1550 			{ "Platform Location Time", "s4607.ploc.time",
1551 			FT_UINT32, BASE_CUSTOM,
1552 			CF_FUNC(prt_millisec), 0x0,
1553 			NULL, HFILL }
1554 		},
1555 		{ &hf_4607_platloc_latitude,
1556 			{ "Platform Position Latitude", "s4607.ploc.lat",
1557 			FT_INT32, BASE_CUSTOM,
1558 			CF_FUNC(prt_sa32), 0x0,
1559 			NULL, HFILL }
1560 		},
1561 		{ &hf_4607_platloc_longitude,
1562 			{ "Platform Position Longitude", "s4607.ploc.lon",
1563 			FT_UINT32, BASE_CUSTOM,
1564 			CF_FUNC(prt_ba32), 0x0,
1565 			NULL, HFILL }
1566 		},
1567 		{ &hf_4607_platloc_altitude,
1568 			{ "Platform Position Altitude", "s4607.ploc.alt",
1569 			FT_INT32, BASE_CUSTOM,
1570 			CF_FUNC(prt_centimeters), 0x0,
1571 			NULL, HFILL }
1572 		},
1573 		{ &hf_4607_platloc_track,
1574 			{ "Platform Track", "s4607.ploc.track",
1575 			FT_UINT16, BASE_CUSTOM,
1576 			CF_FUNC(prt_ba16), 0x0,
1577 			NULL, HFILL }
1578 		},
1579 		{ &hf_4607_platloc_speed,
1580 			{ "Platform Speed", "s4607.ploc.speed",
1581 			FT_UINT32, BASE_CUSTOM,
1582 			CF_FUNC(prt_speed), 0x0,
1583 			NULL, HFILL }
1584 		},
1585 		{ &hf_4607_platloc_vertical_velocity,
1586 			{ "Platform Vertical Velocity", "s4607.ploc.velocity",
1587 			FT_INT8, BASE_CUSTOM,
1588 			CF_FUNC(prt_speed_deci), 0x0,
1589 			NULL, HFILL }
1590 		},
1591 
1592 	};
1593 
1594 	/* Setup protocol subtree array */
1595 	static gint *ett[] = {
1596 		&ett_4607_hdr,
1597 		&ett_4607_seg,
1598 		&ett_4607_rpt,
1599 	};
1600 
1601 	static ei_register_info ei[] = {
1602 		{ &ei_too_short,
1603 			{ "s4607.segment_too_short", PI_MALFORMED, PI_ERROR,
1604 			  "Segment size too small", EXPFILL }},
1605 		{ &ei_bad_length,
1606 			{ "s4607.segment_bad_length", PI_MALFORMED, PI_ERROR,
1607 			  "Bad segment size", EXPFILL }},
1608 		{ &ei_bad_packet_size,
1609 			{ "s4607.bad_packet_size", PI_MALFORMED, PI_ERROR,
1610 			  "Bad packet size field", EXPFILL }}
1611 	};
1612 
1613 	expert_module_t* expert_4607;
1614 
1615 	proto_stanag4607 = proto_register_protocol (
1616 	    "STANAG 4607 (GMTI Format)", /* name       */
1617 	    "STANAG 4607",      /* short name */
1618 	    "s4607"       /* abbrev     */
1619 	);
1620 
1621 	proto_register_field_array(proto_stanag4607, hf, array_length(hf));
1622 	proto_register_subtree_array(ett, array_length(ett));
1623 	expert_4607 = expert_register_protocol(proto_stanag4607);
1624 	expert_register_field_array(expert_4607, ei, array_length(ei));
1625 
1626 	stanag4607_handle = register_dissector("STANAG 4607", dissect_stanag4607, proto_stanag4607);
1627 	/* prefs_register_protocol(proto_stanag4607, proto_reg_handoff_stanag4607); */
1628 }
1629 
1630 void
proto_reg_handoff_stanag4607(void)1631 proto_reg_handoff_stanag4607(void)
1632 {
1633 	dissector_add_uint("wtap_encap", WTAP_ENCAP_STANAG_4607, stanag4607_handle);
1634 }
1635 
1636 /*
1637  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1638  *
1639  * Local variables:
1640  * c-basic-offset: 8
1641  * tab-width: 8
1642  * indent-tabs-mode: t
1643  * End:
1644  *
1645  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1646  * :indentSize=8:tabSize=8:noTabs=false:
1647  */
1648