opa: Add dissectors for Intel’s Omni-Path Architecture (OPA)
[metze/wireshark/wip.git] / wiretap / stanag4607.c
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  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "config.h"
23
24 #include <errno.h>
25
26 #include "wtap-int.h"
27 #include "file_wrappers.h"
28 #include <wsutil/buffer.h>
29 #include "stanag4607.h"
30
31 typedef struct {
32   time_t base_secs;
33 } stanag4607_t;
34
35 static gboolean is_valid_id(guint16 version_id)
36 {
37 #define VERSION_21 0x3231
38 #define VERSION_30 0x3330
39   if ((version_id != VERSION_21) &&
40       (version_id != VERSION_30))
41      /* Not a stanag4607 file */
42      return FALSE;
43   return TRUE;
44 }
45
46 static gboolean stanag4607_read_file(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
47                                Buffer *buf, int *err, gchar **err_info)
48 {
49   stanag4607_t *stanag4607 = (stanag4607_t *)wth->priv;
50   guint32 millisecs, secs, nsecs;
51   gint64 offset = 0;
52   guint8 stanag_pkt_hdr[37];
53   guint32 packet_size;
54
55   *err = 0;
56
57   /* Combined packet header and segment header */
58   if (!wtap_read_bytes_or_eof(fh, stanag_pkt_hdr, sizeof stanag_pkt_hdr, err, err_info))
59     return FALSE;
60   offset += sizeof stanag_pkt_hdr;
61
62   if (!is_valid_id(pntoh16(&stanag_pkt_hdr[0]))) {
63     *err = WTAP_ERR_BAD_FILE;
64     *err_info = g_strdup("Bad version number");
65     return FALSE;
66   }
67
68   phdr->rec_type = REC_TYPE_PACKET;
69
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) {
73     /*
74      * Probably a corrupt capture file; don't blow up trying
75      * to allocate space for an immensely-large packet.
76      */
77     *err = WTAP_ERR_BAD_FILE;
78     *err_info = g_strdup_printf("stanag4607: File has %" G_GUINT32_FORMAT "d-byte packet, "
79       "bigger than maximum of %u", packet_size, WTAP_MAX_PACKET_SIZE);
80     return FALSE;
81   }
82   phdr->caplen = packet_size;
83   phdr->len = packet_size;
84
85   /* Sadly, the header doesn't contain times; but some segments do */
86   /* So, get the segment header, which is just past the 32-byte header. */
87   phdr->presence_flags = WTAP_HAS_TS;
88
89   /* If no time specified, it's the last baseline time */
90   phdr->ts.secs = stanag4607->base_secs;
91   phdr->ts.nsecs = 0;
92   millisecs = 0;
93
94 #define MISSION_SEGMENT 1
95 #define DWELL_SEGMENT 2
96 #define JOB_DEFINITION_SEGMENT 5
97 #define PLATFORM_LOCATION_SEGMENT 13
98   if (MISSION_SEGMENT == stanag_pkt_hdr[32]) {
99     guint8 mseg[39];
100     struct tm tm;
101
102     if (!wtap_read_bytes(fh, &mseg, sizeof mseg, err, err_info))
103       return FALSE;
104     offset += sizeof mseg;
105
106     tm.tm_year = pntoh16(&mseg[35]) - 1900;
107     tm.tm_mon = mseg[37] - 1;
108     tm.tm_mday = mseg[38];
109     tm.tm_hour = 0;
110     tm.tm_min = 0;
111     tm.tm_sec = 0;
112     tm.tm_isdst = -1;
113     stanag4607->base_secs = mktime(&tm);
114     phdr->ts.secs = stanag4607->base_secs;
115   }
116   else if (PLATFORM_LOCATION_SEGMENT == stanag_pkt_hdr[32]) {
117     if (!wtap_read_bytes(fh, &millisecs, sizeof millisecs, err, err_info))
118       return FALSE;
119     offset += sizeof millisecs;
120     millisecs = g_ntohl(millisecs);
121   }
122   else if (DWELL_SEGMENT == stanag_pkt_hdr[32]) {
123     guint8 dseg[19];
124     if (!wtap_read_bytes(fh, &dseg, sizeof dseg, err, err_info))
125       return FALSE;
126     offset += sizeof dseg;
127     millisecs = pntoh32(&dseg[15]);
128   }
129   if (0 != millisecs) {
130     secs = millisecs/1000;
131     nsecs = (millisecs - 1000 * secs) * 1000000;
132     phdr->ts.secs = stanag4607->base_secs + secs;
133     phdr->ts.nsecs = nsecs;
134   }
135
136   /* wind back to the start of the packet ... */
137   if (file_seek(fh, - offset, SEEK_CUR, err) == -1)
138     return FALSE;
139
140   return wtap_read_packet_bytes(fh, buf, packet_size, err, err_info);
141 }
142
143 static gboolean stanag4607_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
144 {
145   gint64 offset;
146
147   *err = 0;
148
149   offset = file_tell(wth->fh);
150
151   *data_offset = offset;
152
153   return stanag4607_read_file(wth, wth->fh, &wth->phdr, wth->frame_buffer, err, err_info);
154 }
155
156 static gboolean stanag4607_seek_read(wtap *wth, gint64 seek_off,
157                                struct wtap_pkthdr *phdr,
158                                Buffer *buf, int *err, gchar **err_info)
159 {
160   if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
161     return FALSE;
162
163   return stanag4607_read_file(wth, wth->random_fh, phdr, buf, err, err_info);
164 }
165
166 wtap_open_return_val stanag4607_open(wtap *wth, int *err, gchar **err_info)
167 {
168   guint16 version_id;
169   stanag4607_t *stanag4607;
170
171   if (!wtap_read_bytes(wth->fh, &version_id, sizeof version_id, err, err_info))
172     return (*err != WTAP_ERR_SHORT_READ) ? WTAP_OPEN_ERROR : WTAP_OPEN_NOT_MINE;
173
174   if (!is_valid_id(GUINT16_TO_BE(version_id)))
175      /* Not a stanag4607 file */
176      return WTAP_OPEN_NOT_MINE;
177
178   /* seek back to the start of the file  */
179   if (file_seek(wth->fh, 0, SEEK_SET, err) == -1)
180     return WTAP_OPEN_ERROR;
181
182   wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_STANAG_4607;
183   wth->file_encap = WTAP_ENCAP_STANAG_4607;
184   wth->snapshot_length = 0; /* not known */
185
186   stanag4607 = (stanag4607_t *)g_malloc(sizeof(stanag4607_t));
187   wth->priv = (void *)stanag4607;
188   stanag4607->base_secs = 0; /* unknown as of yet */
189
190   wth->subtype_read = stanag4607_read;
191   wth->subtype_seek_read = stanag4607_seek_read;
192   wth->file_tsprec = WTAP_TSPREC_MSEC;
193
194   return WTAP_OPEN_MINE;
195 }
196
197 /*
198  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
199  *
200  * Local Variables:
201  * c-basic-offset: 2
202  * tab-width: 8
203  * indent-tabs-mode: nil
204  * End:
205  *
206  * vi: set shiftwidth=2 tabstop=8 expandtab:
207  * :indentSize=2:tabSize=8:noTabs=true:
208  */