/src/wireshark/wiretap/stanag4607.c
Line | Count | Source |
1 | | /* stanag4607.c |
2 | | * |
3 | | * STANAG 4607 file reading |
4 | | * |
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 |
7 | | * Machine: |
8 | | * |
9 | | * https://web.archive.org/web/20130223054955/http://www.nato.int/structur/AC/224/standard/4607/4607.htm |
10 | | * |
11 | | * https://nso.nato.int/nso/zPublic/ap/aedp-7(2).pdf |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | */ |
15 | | |
16 | | #include "config.h" |
17 | | #include "stanag4607.h" |
18 | | |
19 | | #include "wtap_module.h" |
20 | | #include "file_wrappers.h" |
21 | | #include <wsutil/buffer.h> |
22 | | #include <wsutil/pint.h> |
23 | | |
24 | | typedef struct { |
25 | | time_t base_secs; |
26 | | } stanag4607_t; |
27 | | |
28 | 0 | #define PKT_HDR_SIZE 32 /* size of a packet header */ |
29 | 0 | #define SEG_HDR_SIZE 5 /* size of a segment header */ |
30 | | |
31 | | static int stanag4607_file_type_subtype = -1; |
32 | | |
33 | | void register_stanag4607(void); |
34 | | |
35 | | static bool is_valid_id(uint16_t version_id) |
36 | 0 | { |
37 | 0 | #define VERSION_21 0x3231 |
38 | 0 | #define VERSION_30 0x3330 |
39 | 0 | if ((version_id != VERSION_21) && |
40 | 0 | (version_id != VERSION_30)) |
41 | | /* Not a stanag4607 file */ |
42 | 0 | return false; |
43 | 0 | return true; |
44 | 0 | } |
45 | | |
46 | | static bool stanag4607_read_file(wtap *wth, FILE_T fh, wtap_rec *rec, |
47 | | int *err, char **err_info) |
48 | 0 | { |
49 | 0 | stanag4607_t *stanag4607 = (stanag4607_t *)wth->priv; |
50 | 0 | uint32_t millisecs, secs, nsecs; |
51 | 0 | int64_t offset = 0; |
52 | 0 | uint8_t stanag_pkt_hdr[PKT_HDR_SIZE+SEG_HDR_SIZE]; |
53 | 0 | uint32_t packet_size; |
54 | |
|
55 | 0 | *err = 0; |
56 | | |
57 | | /* Combined packet header and segment header */ |
58 | 0 | if (!wtap_read_bytes_or_eof(fh, stanag_pkt_hdr, sizeof stanag_pkt_hdr, err, err_info)) |
59 | 0 | return false; |
60 | 0 | offset += sizeof stanag_pkt_hdr; |
61 | |
|
62 | 0 | if (!is_valid_id(pntohu16(&stanag_pkt_hdr[0]))) { |
63 | 0 | *err = WTAP_ERR_BAD_FILE; |
64 | 0 | *err_info = g_strdup("Bad version number"); |
65 | 0 | return false; |
66 | 0 | } |
67 | | |
68 | 0 | wtap_setup_packet_rec(rec, wth->file_encap); |
69 | 0 | rec->block = wtap_block_create(WTAP_BLOCK_PACKET); |
70 | | |
71 | | /* The next 4 bytes are the packet length */ |
72 | 0 | packet_size = pntohu32(&stanag_pkt_hdr[2]); |
73 | 0 | if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) { |
74 | | /* |
75 | | * Probably a corrupt capture file; don't blow up trying |
76 | | * to allocate space for an immensely-large packet. |
77 | | */ |
78 | 0 | *err = WTAP_ERR_BAD_FILE; |
79 | 0 | *err_info = ws_strdup_printf("stanag4607: File has %" PRIu32 "d-byte packet, " |
80 | 0 | "bigger than maximum of %u", packet_size, WTAP_MAX_PACKET_SIZE_STANDARD); |
81 | 0 | return false; |
82 | 0 | } |
83 | 0 | if (packet_size < PKT_HDR_SIZE+SEG_HDR_SIZE) { |
84 | | /* |
85 | | * Probably a corrupt capture file; don't, for example, loop |
86 | | * infinitely if the size is zero. |
87 | | */ |
88 | 0 | *err = WTAP_ERR_BAD_FILE; |
89 | 0 | *err_info = ws_strdup_printf("stanag4607: File has %" PRIu32 "d-byte packet, " |
90 | 0 | "smaller than minimum of %u", packet_size, PKT_HDR_SIZE+SEG_HDR_SIZE); |
91 | 0 | return false; |
92 | 0 | } |
93 | 0 | rec->rec_header.packet_header.caplen = packet_size; |
94 | 0 | rec->rec_header.packet_header.len = packet_size; |
95 | | |
96 | | /* Sadly, the header doesn't contain times; but some segments do */ |
97 | | /* So, get the segment header, which is just past the 32-byte header. */ |
98 | 0 | rec->presence_flags = WTAP_HAS_TS; |
99 | | |
100 | | /* If no time specified, it's the last baseline time */ |
101 | 0 | rec->ts.secs = stanag4607->base_secs; |
102 | 0 | rec->ts.nsecs = 0; |
103 | 0 | millisecs = 0; |
104 | |
|
105 | 0 | #define MISSION_SEGMENT 1 |
106 | 0 | #define DWELL_SEGMENT 2 |
107 | 0 | #define JOB_DEFINITION_SEGMENT 5 |
108 | 0 | #define PLATFORM_LOCATION_SEGMENT 13 |
109 | 0 | if (MISSION_SEGMENT == stanag_pkt_hdr[32]) { |
110 | 0 | uint8_t mseg[39]; |
111 | 0 | struct tm tm; |
112 | |
|
113 | 0 | if (!wtap_read_bytes(fh, &mseg, sizeof mseg, err, err_info)) |
114 | 0 | return false; |
115 | 0 | offset += sizeof mseg; |
116 | |
|
117 | 0 | tm.tm_year = pntohu16(&mseg[35]) - 1900; |
118 | 0 | tm.tm_mon = mseg[37] - 1; |
119 | 0 | tm.tm_mday = mseg[38]; |
120 | 0 | tm.tm_hour = 0; |
121 | 0 | tm.tm_min = 0; |
122 | 0 | tm.tm_sec = 0; |
123 | 0 | tm.tm_isdst = -1; |
124 | 0 | stanag4607->base_secs = mktime(&tm); |
125 | 0 | rec->ts.secs = stanag4607->base_secs; |
126 | 0 | } |
127 | 0 | else if (PLATFORM_LOCATION_SEGMENT == stanag_pkt_hdr[32]) { |
128 | 0 | if (!wtap_read_bytes(fh, &millisecs, sizeof millisecs, err, err_info)) |
129 | 0 | return false; |
130 | 0 | offset += sizeof millisecs; |
131 | 0 | millisecs = g_ntohl(millisecs); |
132 | 0 | } |
133 | 0 | else if (DWELL_SEGMENT == stanag_pkt_hdr[32]) { |
134 | 0 | uint8_t dseg[19]; |
135 | 0 | if (!wtap_read_bytes(fh, &dseg, sizeof dseg, err, err_info)) |
136 | 0 | return false; |
137 | 0 | offset += sizeof dseg; |
138 | 0 | millisecs = pntohu32(&dseg[15]); |
139 | 0 | } |
140 | 0 | if (0 != millisecs) { |
141 | 0 | secs = millisecs/1000; |
142 | 0 | nsecs = (millisecs - 1000 * secs) * 1000000; |
143 | 0 | rec->ts.secs = stanag4607->base_secs + secs; |
144 | 0 | rec->ts.nsecs = nsecs; |
145 | 0 | } |
146 | | |
147 | | /* wind back to the start of the packet ... */ |
148 | 0 | if (file_seek(fh, - offset, SEEK_CUR, err) == -1) |
149 | 0 | return false; |
150 | | |
151 | 0 | return wtap_read_bytes_buffer(fh, &rec->data, packet_size, err, err_info); |
152 | 0 | } |
153 | | |
154 | | static bool stanag4607_read(wtap *wth, wtap_rec *rec, |
155 | | int *err, char **err_info, int64_t *data_offset) |
156 | 0 | { |
157 | 0 | *data_offset = file_tell(wth->fh); |
158 | |
|
159 | 0 | return stanag4607_read_file(wth, wth->fh, rec, err, err_info); |
160 | 0 | } |
161 | | |
162 | | static bool stanag4607_seek_read(wtap *wth, int64_t seek_off, wtap_rec *rec, |
163 | | int *err, char **err_info) |
164 | 0 | { |
165 | 0 | if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) |
166 | 0 | return false; |
167 | | |
168 | 0 | return stanag4607_read_file(wth, wth->random_fh, rec, err, err_info); |
169 | 0 | } |
170 | | |
171 | | wtap_open_return_val stanag4607_open(wtap *wth, int *err, char **err_info) |
172 | 0 | { |
173 | 0 | uint16_t version_id; |
174 | 0 | stanag4607_t *stanag4607; |
175 | |
|
176 | 0 | if (!wtap_read_bytes(wth->fh, &version_id, sizeof version_id, err, err_info)) |
177 | 0 | return (*err != WTAP_ERR_SHORT_READ) ? WTAP_OPEN_ERROR : WTAP_OPEN_NOT_MINE; |
178 | | |
179 | 0 | if (!is_valid_id(GUINT16_TO_BE(version_id))) |
180 | | /* Not a stanag4607 file */ |
181 | 0 | return WTAP_OPEN_NOT_MINE; |
182 | | |
183 | | /* seek back to the start of the file */ |
184 | 0 | if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) |
185 | 0 | return WTAP_OPEN_ERROR; |
186 | | |
187 | 0 | wth->file_type_subtype = stanag4607_file_type_subtype; |
188 | 0 | wth->file_encap = WTAP_ENCAP_STANAG_4607; |
189 | 0 | wth->snapshot_length = 0; /* not known */ |
190 | |
|
191 | 0 | stanag4607 = g_new(stanag4607_t, 1); |
192 | 0 | wth->priv = (void *)stanag4607; |
193 | 0 | stanag4607->base_secs = 0; /* unknown as of yet */ |
194 | |
|
195 | 0 | wth->subtype_read = stanag4607_read; |
196 | 0 | wth->subtype_seek_read = stanag4607_seek_read; |
197 | 0 | wth->file_tsprec = WTAP_TSPREC_MSEC; |
198 | | |
199 | | /* |
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. |
204 | | */ |
205 | 0 | wtap_add_generated_idb(wth); |
206 | |
|
207 | 0 | return WTAP_OPEN_MINE; |
208 | 0 | } |
209 | | |
210 | | static const struct supported_block_type stanag4607_blocks_supported[] = { |
211 | | /* |
212 | | * We support packet blocks, with no comments or other options. |
213 | | */ |
214 | | { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED } |
215 | | }; |
216 | | |
217 | | static const struct file_type_subtype_info stanag4607_info = { |
218 | | "STANAG 4607 Format", "stanag4607", NULL, NULL, |
219 | | false, BLOCKS_SUPPORTED(stanag4607_blocks_supported), |
220 | | NULL, NULL, NULL |
221 | | }; |
222 | | |
223 | | void register_stanag4607(void) |
224 | 15 | { |
225 | 15 | stanag4607_file_type_subtype = wtap_register_file_type_subtype(&stanag4607_info); |
226 | | |
227 | | /* |
228 | | * Register name for backwards compatibility with the |
229 | | * wtap_filetypes table in Lua. |
230 | | */ |
231 | 15 | wtap_register_backwards_compatibility_lua_name("STANAG_4607", |
232 | 15 | stanag4607_file_type_subtype); |
233 | 15 | } |
234 | | |
235 | | /* |
236 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
237 | | * |
238 | | * Local Variables: |
239 | | * c-basic-offset: 2 |
240 | | * tab-width: 8 |
241 | | * indent-tabs-mode: nil |
242 | | * End: |
243 | | * |
244 | | * vi: set shiftwidth=2 tabstop=8 expandtab: |
245 | | * :indentSize=2:tabSize=8:noTabs=true: |
246 | | */ |