3 * STANAG 4607 file reading
5 * http://www.nato.int/structur/AC/224/standard/4607/4607e_JAS_ED3.pdf
6 * That is now missing from that site, but is available on the Wayback
9 * https://web.archive.org/web/20130223054955/http://www.nato.int/structur/AC/224/standard/4607/4607.htm
11 * https://nso.nato.int/nso/zPublic/ap/aedp-7(2).pdf
13 * SPDX-License-Identifier: GPL-2.0-or-later
17 #include "stanag4607.h"
20 #include "file_wrappers.h"
21 #include <wsutil/buffer.h>
27 #define PKT_HDR_SIZE 32 /* size of a packet header */
28 #define SEG_HDR_SIZE 5 /* size of a segment header */
30 static int stanag4607_file_type_subtype
= -1;
32 void register_stanag4607(void);
34 static bool is_valid_id(uint16_t version_id
)
36 #define VERSION_21 0x3231
37 #define VERSION_30 0x3330
38 if ((version_id
!= VERSION_21
) &&
39 (version_id
!= VERSION_30
))
40 /* Not a stanag4607 file */
45 static bool stanag4607_read_file(wtap
*wth
, FILE_T fh
, wtap_rec
*rec
,
46 Buffer
*buf
, int *err
, char **err_info
)
48 stanag4607_t
*stanag4607
= (stanag4607_t
*)wth
->priv
;
49 uint32_t millisecs
, secs
, nsecs
;
51 uint8_t stanag_pkt_hdr
[PKT_HDR_SIZE
+SEG_HDR_SIZE
];
56 /* Combined packet header and segment header */
57 if (!wtap_read_bytes_or_eof(fh
, stanag_pkt_hdr
, sizeof stanag_pkt_hdr
, err
, err_info
))
59 offset
+= sizeof stanag_pkt_hdr
;
61 if (!is_valid_id(pntoh16(&stanag_pkt_hdr
[0]))) {
62 *err
= WTAP_ERR_BAD_FILE
;
63 *err_info
= g_strdup("Bad version number");
67 rec
->rec_type
= REC_TYPE_PACKET
;
68 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
70 /* The next 4 bytes are the packet length */
71 packet_size
= pntoh32(&stanag_pkt_hdr
[2]);
72 if (packet_size
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
74 * Probably a corrupt capture file; don't blow up trying
75 * to allocate space for an immensely-large packet.
77 *err
= WTAP_ERR_BAD_FILE
;
78 *err_info
= ws_strdup_printf("stanag4607: File has %" PRIu32
"d-byte packet, "
79 "bigger than maximum of %u", packet_size
, WTAP_MAX_PACKET_SIZE_STANDARD
);
82 if (packet_size
< PKT_HDR_SIZE
+SEG_HDR_SIZE
) {
84 * Probably a corrupt capture file; don't, for example, loop
85 * infinitely if the size is zero.
87 *err
= WTAP_ERR_BAD_FILE
;
88 *err_info
= ws_strdup_printf("stanag4607: File has %" PRIu32
"d-byte packet, "
89 "smaller than minimum of %u", packet_size
, PKT_HDR_SIZE
+SEG_HDR_SIZE
);
92 rec
->rec_header
.packet_header
.caplen
= packet_size
;
93 rec
->rec_header
.packet_header
.len
= packet_size
;
95 /* Sadly, the header doesn't contain times; but some segments do */
96 /* So, get the segment header, which is just past the 32-byte header. */
97 rec
->presence_flags
= WTAP_HAS_TS
;
99 /* If no time specified, it's the last baseline time */
100 rec
->ts
.secs
= stanag4607
->base_secs
;
104 #define MISSION_SEGMENT 1
105 #define DWELL_SEGMENT 2
106 #define JOB_DEFINITION_SEGMENT 5
107 #define PLATFORM_LOCATION_SEGMENT 13
108 if (MISSION_SEGMENT
== stanag_pkt_hdr
[32]) {
112 if (!wtap_read_bytes(fh
, &mseg
, sizeof mseg
, err
, err_info
))
114 offset
+= sizeof mseg
;
116 tm
.tm_year
= pntoh16(&mseg
[35]) - 1900;
117 tm
.tm_mon
= mseg
[37] - 1;
118 tm
.tm_mday
= mseg
[38];
123 stanag4607
->base_secs
= mktime(&tm
);
124 rec
->ts
.secs
= stanag4607
->base_secs
;
126 else if (PLATFORM_LOCATION_SEGMENT
== stanag_pkt_hdr
[32]) {
127 if (!wtap_read_bytes(fh
, &millisecs
, sizeof millisecs
, err
, err_info
))
129 offset
+= sizeof millisecs
;
130 millisecs
= g_ntohl(millisecs
);
132 else if (DWELL_SEGMENT
== stanag_pkt_hdr
[32]) {
134 if (!wtap_read_bytes(fh
, &dseg
, sizeof dseg
, err
, err_info
))
136 offset
+= sizeof dseg
;
137 millisecs
= pntoh32(&dseg
[15]);
139 if (0 != millisecs
) {
140 secs
= millisecs
/1000;
141 nsecs
= (millisecs
- 1000 * secs
) * 1000000;
142 rec
->ts
.secs
= stanag4607
->base_secs
+ secs
;
143 rec
->ts
.nsecs
= nsecs
;
146 /* wind back to the start of the packet ... */
147 if (file_seek(fh
, - offset
, SEEK_CUR
, err
) == -1)
150 return wtap_read_packet_bytes(fh
, buf
, packet_size
, err
, err_info
);
153 static bool stanag4607_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
154 int *err
, char **err_info
, int64_t *data_offset
)
156 *data_offset
= file_tell(wth
->fh
);
158 return stanag4607_read_file(wth
, wth
->fh
, rec
, buf
, err
, err_info
);
161 static bool stanag4607_seek_read(wtap
*wth
, int64_t seek_off
,
163 Buffer
*buf
, int *err
, char **err_info
)
165 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
168 return stanag4607_read_file(wth
, wth
->random_fh
, rec
, buf
, err
, err_info
);
171 wtap_open_return_val
stanag4607_open(wtap
*wth
, int *err
, char **err_info
)
174 stanag4607_t
*stanag4607
;
176 if (!wtap_read_bytes(wth
->fh
, &version_id
, sizeof version_id
, err
, err_info
))
177 return (*err
!= WTAP_ERR_SHORT_READ
) ? WTAP_OPEN_ERROR
: WTAP_OPEN_NOT_MINE
;
179 if (!is_valid_id(GUINT16_TO_BE(version_id
)))
180 /* Not a stanag4607 file */
181 return WTAP_OPEN_NOT_MINE
;
183 /* seek back to the start of the file */
184 if (file_seek(wth
->fh
, 0, SEEK_SET
, err
) == -1)
185 return WTAP_OPEN_ERROR
;
187 wth
->file_type_subtype
= stanag4607_file_type_subtype
;
188 wth
->file_encap
= WTAP_ENCAP_STANAG_4607
;
189 wth
->snapshot_length
= 0; /* not known */
191 stanag4607
= g_new(stanag4607_t
, 1);
192 wth
->priv
= (void *)stanag4607
;
193 stanag4607
->base_secs
= 0; /* unknown as of yet */
195 wth
->subtype_read
= stanag4607_read
;
196 wth
->subtype_seek_read
= stanag4607_seek_read
;
197 wth
->file_tsprec
= WTAP_TSPREC_MSEC
;
200 * Add an IDB; we don't know how many interfaces were
201 * involved, so we just say one interface, about which
202 * we only know the link-layer type, snapshot length,
203 * and time stamp resolution.
205 wtap_add_generated_idb(wth
);
207 return WTAP_OPEN_MINE
;
210 static const struct supported_block_type stanag4607_blocks_supported
[] = {
212 * We support packet blocks, with no comments or other options.
214 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
217 static const struct file_type_subtype_info stanag4607_info
= {
218 "STANAG 4607 Format", "stanag4607", NULL
, NULL
,
219 false, BLOCKS_SUPPORTED(stanag4607_blocks_supported
),
223 void register_stanag4607(void)
225 stanag4607_file_type_subtype
= wtap_register_file_type_subtype(&stanag4607_info
);
228 * Register name for backwards compatibility with the
229 * wtap_filetypes table in Lua.
231 wtap_register_backwards_compatibility_lua_name("STANAG_4607",
232 stanag4607_file_type_subtype
);
236 * Editor modelines - https://www.wireshark.org/tools/modelines.html
241 * indent-tabs-mode: nil
244 * vi: set shiftwidth=2 tabstop=8 expandtab:
245 * :indentSize=2:tabSize=8:noTabs=true: