4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "file_wrappers.h"
35 guint32 Size; /* Total size of Header in bytes (included Signature) */
36 guint32 Version; /* Identify version and so the format of this record */
37 guint32 DataSize; /* Total size of data included in the Info Record (except the header size) */
38 guint32 FileType; /* Type of the file */
39 guint32 Reserved[3]; /* Reserved for future use */
44 guint32 Type; /* Id of the attribute */
45 guint16 Size; /* Size of the data part of the attribute (not including header size) */
46 guint16 Nb; /* Number of elements */
47 }t_5VW_Attributes_Header;
50 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAAU /* signature */
52 #define CST_5VW_INFO_RECORD_VERSION 0x00010000U /* version */
54 #define CST_5VW_DECALE_FILE_TYPE 24
55 #define CST_5VW_SECTION_CAPTURES 0x08U
56 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
57 #define CST_5VW_FLAT_FILE 0x10000000U
58 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
59 #define CST_5VW_FAMILY_CAP_ETH 0x01U
60 #define CST_5VW_FAMILY_CAP_WAN 0x02U
61 #define CST_5VW_DECALE_FILE_FAMILY 12
62 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
63 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
64 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
65 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
67 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000U
69 #define CST_5VW_FRAME_RECORD 0x00000000U
70 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEEU
74 t_5VW_Info_Header Info_Header;
75 t_5VW_Attributes_Header HeaderDateCreation;
77 t_5VW_Attributes_Header HeaderNbFrames;
78 guint32 TramesStockeesInFile;
79 }t_5VW_Capture_Header;
83 guint32 Key; /* 0x3333EEEE */
84 guint16 HeaderSize; /* Actual size of this header in bytes (32) */
85 guint16 HeaderType; /* Exact type of this header (0x4000) */
86 guint32 RecType; /* Type of record */
87 guint32 RecSubType; /* Subtype of record */
88 guint32 RecSize; /* Size of one record */
89 guint32 RecNb; /* Number of records */
92 guint32 RecInfo; /* Info about Alarm / Event / Frame captured */
93 }t_5VW_TimeStamped_Header;
96 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000U
97 #define CST_5VW_IA_DATE_CREATION 0x80000007U /* Struct t_Attrib_Date_Create */
98 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000U
99 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
100 #define CST_5VW_SYSTEM_RECORD 0x00000000U
102 static int _5views_read(wtap *wth, int *err, gchar **err_info,
103 gint64 *data_offset);
104 static int _5views_seek_read(wtap *wth, gint64 seek_off,
105 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
106 static int _5views_read_header(wtap *wth, FILE_T fh, t_5VW_TimeStamped_Header *hdr,
107 struct wtap_pkthdr *phdr, int *err, gchar **err_info);
109 static gboolean _5views_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const guint8 *pd, int *err);
110 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err);
113 int _5views_open(wtap *wth, int *err, gchar **err_info)
116 t_5VW_Capture_Header Capture_Header;
117 int encap = WTAP_ENCAP_UNKNOWN;
119 errno = WTAP_ERR_CANT_READ;
120 bytes_read = file_read(&Capture_Header.Info_Header, sizeof(t_5VW_Info_Header), wth->fh);
121 if (bytes_read != sizeof(t_5VW_Info_Header)) {
122 *err = file_error(wth->fh, err_info);
123 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
128 /* Check whether that's 5Views format or not */
129 if(Capture_Header.Info_Header.Signature != CST_5VW_INFO_HEADER_KEY)
135 Capture_Header.Info_Header.Version =
136 pletoh32(&Capture_Header.Info_Header.Version);
137 switch (Capture_Header.Info_Header.Version) {
139 case CST_5VW_INFO_RECORD_VERSION:
143 *err = WTAP_ERR_UNSUPPORTED;
144 *err_info = g_strdup_printf("5views: header version %u unsupported", Capture_Header.Info_Header.Version);
148 /* Check File Type */
149 Capture_Header.Info_Header.FileType =
150 pletoh32(&Capture_Header.Info_Header.FileType);
151 if((Capture_Header.Info_Header.FileType & CST_5VW_CAPTURE_FILE_TYPE_MASK) != CST_5VW_CAPTURE_FILEID)
153 *err = WTAP_ERR_UNSUPPORTED;
154 *err_info = g_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header.Info_Header.Version);
158 /* Check possible Encap */
159 switch (Capture_Header.Info_Header.FileType) {
160 case CST_5VW_CAPTURE_ETH_FILEID:
161 encap = WTAP_ENCAP_ETHERNET;
163 /* case CST_5VW_CAPTURE_WAN_FILEID:
167 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
168 *err_info = g_strdup_printf("5views: network type %u unknown or unsupported",
169 Capture_Header.Info_Header.FileType);
173 /* read the remaining header information */
174 bytes_read = file_read(&Capture_Header.HeaderDateCreation, sizeof (t_5VW_Capture_Header) - sizeof(t_5VW_Info_Header), wth->fh);
175 if (bytes_read != sizeof (t_5VW_Capture_Header)- sizeof(t_5VW_Info_Header) ) {
176 *err = file_error(wth->fh, err_info);
178 *err = WTAP_ERR_SHORT_READ;
182 /* This is a 5views capture file */
183 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_5VIEWS;
184 wth->subtype_read = _5views_read;
185 wth->subtype_seek_read = _5views_seek_read;
186 wth->file_encap = encap;
187 wth->snapshot_length = 0; /* not available in header */
188 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
193 /* Read the next packet */
195 _5views_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
197 t_5VW_TimeStamped_Header TimeStamped_Header;
200 * Keep reading until we see a record with a subtype of
201 * CST_5VW_FRAME_RECORD.
205 *data_offset = file_tell(wth->fh);
207 /* Read record header. */
208 if (!_5views_read_header(wth, wth->fh, &TimeStamped_Header,
209 &wth->phdr, err, err_info))
212 if (TimeStamped_Header.RecSubType == CST_5VW_FRAME_RECORD) {
214 * OK, this is a packet.
220 * Not a packet - skip to the next record.
222 if (file_seek(wth->fh, TimeStamped_Header.RecSize, SEEK_CUR, err) == -1)
226 if (wth->phdr.caplen > WTAP_MAX_PACKET_SIZE) {
228 * Probably a corrupt capture file; don't blow up trying
229 * to allocate space for an immensely-large packet.
231 *err = WTAP_ERR_BAD_FILE;
232 *err_info = g_strdup_printf("5views: File has %u-byte packet, bigger than maximum of %u",
233 wth->phdr.caplen, WTAP_MAX_PACKET_SIZE);
237 if (!wtap_read_packet_bytes(wth->fh, wth->frame_buffer,
238 wth->phdr.caplen, err, err_info))
240 return REC_TYPE_PACKET;
244 _5views_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
245 Buffer *buf, int *err, gchar **err_info)
247 t_5VW_TimeStamped_Header TimeStamped_Header;
249 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
255 if (!_5views_read_header(wth, wth->random_fh, &TimeStamped_Header,
256 phdr, err, err_info)) {
258 *err = WTAP_ERR_SHORT_READ;
263 * Read the packet data.
265 if (!wtap_read_packet_bytes(wth->random_fh, buf, phdr->caplen,
268 return REC_TYPE_PACKET;
271 /* Read the header of the next packet. Return TRUE on success, FALSE
274 _5views_read_header(wtap *wth, FILE_T fh, t_5VW_TimeStamped_Header *hdr,
275 struct wtap_pkthdr *phdr, int *err, gchar **err_info)
277 int bytes_read, bytes_to_read;
279 bytes_to_read = sizeof(t_5VW_TimeStamped_Header);
281 /* Read record header. */
282 bytes_read = file_read(hdr, bytes_to_read, fh);
283 if (bytes_read != bytes_to_read) {
284 *err = file_error(fh, err_info);
285 if (*err == 0 && bytes_read != 0) {
286 *err = WTAP_ERR_SHORT_READ;
291 hdr->Key = pletoh32(&hdr->Key);
292 if (hdr->Key != CST_5VW_RECORDS_HEADER_KEY) {
293 *err = WTAP_ERR_BAD_FILE;
294 *err_info = g_strdup_printf("5views: Time-stamped header has bad key value 0x%08X",
299 hdr->RecSubType = pletoh32(&hdr->RecSubType);
300 hdr->RecSize = pletoh32(&hdr->RecSize);
301 hdr->Utc = pletoh32(&hdr->Utc);
302 hdr->NanoSecondes = pletoh32(&hdr->NanoSecondes);
304 phdr->presence_flags = WTAP_HAS_TS;
305 phdr->ts.secs = hdr->Utc;
306 phdr->ts.nsecs = hdr->NanoSecondes;
307 phdr->caplen = hdr->RecSize;
308 phdr->len = hdr->RecSize;
310 switch (wth->file_encap) {
312 case WTAP_ENCAP_ETHERNET:
313 /* We assume there's no FCS in this frame. */
314 phdr->pseudo_header.eth.fcs_len = 0;
325 static const int wtap_encap[] = {
326 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
327 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ethernet */
329 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
331 /* Returns 0 if we could write the specified encapsulation type,
332 an error indication otherwise. */
333 int _5views_dump_can_write_encap(int encap)
335 /* Per-packet encapsulations aren't supported. */
336 if (encap == WTAP_ENCAP_PER_PACKET)
337 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
339 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
340 return WTAP_ERR_UNSUPPORTED_ENCAP;
345 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
347 gboolean _5views_dump_open(wtap_dumper *wdh, int *err)
349 _5views_dump_t *_5views;
351 /* We can't fill in all the fields in the file header, as we
352 haven't yet written any packets. As we'll have to rewrite
353 the header when we've written out all the packets, we just
354 skip over the header for now. */
355 if (wtap_dump_file_seek(wdh, sizeof(t_5VW_Capture_Header), SEEK_SET, err) == -1)
358 /* This is a 5Views file */
359 wdh->subtype_write = _5views_dump;
360 wdh->subtype_close = _5views_dump_close;
361 _5views = (_5views_dump_t *)g_malloc(sizeof(_5views_dump_t));
362 wdh->priv = (void *)_5views;
363 _5views->nframes = 0;
368 /* Write a record for a packet to a dump file.
369 Returns TRUE on success, FALSE on failure. */
370 static gboolean _5views_dump(wtap_dumper *wdh,
371 const struct wtap_pkthdr *phdr,
372 const guint8 *pd, int *err)
374 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
375 t_5VW_TimeStamped_Header HeaderFrame;
377 /* Don't write out something bigger than we can read. */
378 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
379 *err = WTAP_ERR_PACKET_TOO_LARGE;
384 /* constant fields */
385 HeaderFrame.Key = GUINT32_TO_LE(CST_5VW_RECORDS_HEADER_KEY);
386 HeaderFrame.HeaderSize = GUINT16_TO_LE(sizeof(t_5VW_TimeStamped_Header));
387 HeaderFrame.HeaderType = GUINT16_TO_LE(CST_5VW_TIMESTAMPED_HEADER_TYPE);
388 HeaderFrame.RecType = GUINT32_TO_LE(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
389 HeaderFrame.RecSubType = GUINT32_TO_LE(CST_5VW_FRAME_RECORD);
390 HeaderFrame.RecNb = GUINT32_TO_LE(1);
392 /* record-dependent fields */
393 HeaderFrame.Utc = GUINT32_TO_LE(phdr->ts.secs);
394 HeaderFrame.NanoSecondes = GUINT32_TO_LE(phdr->ts.nsecs);
395 HeaderFrame.RecSize = GUINT32_TO_LE(phdr->len);
396 HeaderFrame.RecInfo = GUINT32_TO_LE(0);
398 /* write the record header */
399 if (!wtap_dump_file_write(wdh, &HeaderFrame,
400 sizeof(t_5VW_TimeStamped_Header), err))
404 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
412 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
414 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
415 t_5VW_Capture_Header file_hdr;
417 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
420 /* fill in the Info_Header */
421 file_hdr.Info_Header.Signature = GUINT32_TO_LE(CST_5VW_INFO_HEADER_KEY);
422 file_hdr.Info_Header.Size = GUINT32_TO_LE(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
423 file_hdr.Info_Header.Version = GUINT32_TO_LE(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
424 file_hdr.Info_Header.DataSize = GUINT32_TO_LE(sizeof(t_5VW_Attributes_Header)
426 + sizeof(t_5VW_Attributes_Header)
428 /* Total size of data included in the Info Record (except the header size) */
429 file_hdr.Info_Header.FileType = GUINT32_TO_LE(wtap_encap[wdh->encap]); /* Type of the file */
430 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
431 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
432 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
434 /* fill in the HeaderDateCreation */
435 file_hdr.HeaderDateCreation.Type = GUINT32_TO_LE(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
436 file_hdr.HeaderDateCreation.Size = GUINT16_TO_LE(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
437 file_hdr.HeaderDateCreation.Nb = GUINT16_TO_LE(1); /* Number of elements */
439 /* fill in the Time field */
443 file_hdr.Time = GUINT32_TO_LE(time(NULL));
445 /* fill in the Time field */
446 file_hdr.HeaderNbFrames.Type = GUINT32_TO_LE(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
447 file_hdr.HeaderNbFrames.Size = GUINT16_TO_LE(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
448 file_hdr.HeaderNbFrames.Nb = GUINT16_TO_LE(1); /* Number of elements */
450 /* fill in the number of frames saved */
451 file_hdr.TramesStockeesInFile = GUINT32_TO_LE(_5views->nframes);
453 /* Write the file header. */
454 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof(t_5VW_Capture_Header),