6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "file_wrappers.h"
37 guint32 Size; /* Total size of Header in bytes (included Signature) */
38 guint32 Version; /* Identify version and so the format of this record */
39 guint32 DataSize; /* Total size of data included in the Info Record (except the header size) */
40 guint32 FileType; /* Type of the file */
41 guint32 Reserved[3]; /* Reserved for future use */
46 guint32 Type; /* Id of the attribute */
47 guint16 Size; /* Size of the data part of the attribute (not including header size) */
48 guint16 Nb; /* Number of elements */
49 }t_5VW_Attributes_Header;
52 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAAU /* signature */
54 #define CST_5VW_INFO_RECORD_VERSION 0x00010000U /* version */
56 #define CST_5VW_DECALE_FILE_TYPE 24
57 #define CST_5VW_SECTION_CAPTURES 0x08U
58 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
59 #define CST_5VW_FLAT_FILE 0x10000000U
60 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
61 #define CST_5VW_FAMILY_CAP_ETH 0x01U
62 #define CST_5VW_FAMILY_CAP_WAN 0x02U
63 #define CST_5VW_DECALE_FILE_FAMILY 12
64 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
65 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
66 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
67 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
69 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000U
71 #define CST_5VW_FRAME_RECORD 0x00000000U
72 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEEU
76 t_5VW_Info_Header Info_Header;
77 t_5VW_Attributes_Header HeaderDateCreation;
79 t_5VW_Attributes_Header HeaderNbFrames;
80 guint32 TramesStockeesInFile;
81 }t_5VW_Capture_Header;
85 guint32 Key; /* 0x3333EEEE */
86 guint16 HeaderSize; /* Actual size of this header in bytes (32) */
87 guint16 HeaderType; /* Exact type of this header (0x4000) */
88 guint32 RecType; /* Type of record */
89 guint32 RecSubType; /* Subtype of record */
90 guint32 RecSize; /* Size of one record */
91 guint32 RecNb; /* Number of records */
94 guint32 RecInfo; /* Info about Alarm / Event / Frame captured */
95 }t_5VW_TimeStamped_Header;
98 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000U
99 #define CST_5VW_IA_DATE_CREATION 0x80000007U /* Struct t_Attrib_Date_Create */
100 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000U
101 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
102 #define CST_5VW_SYSTEM_RECORD 0x00000000U
104 static gboolean _5views_read(wtap *wth, int *err, gchar **err_info,
105 gint64 *data_offset);
106 static gboolean _5views_read_rec_data(FILE_T fh, guint8 *pd, int length,
107 int *err, gchar **err_info);
108 static int _5views_read_header(wtap *wth, FILE_T fh,
109 t_5VW_TimeStamped_Header *hdr, int *err, gchar **err_info);
110 static gboolean _5views_seek_read(wtap *wth, gint64 seek_off,
111 struct wtap_pkthdr *phdr, guint8 *pd, int length,
112 int *err, gchar **err_info);
115 static gboolean _5views_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const guint8 *pd, int *err);
116 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err);
119 int _5views_open(wtap *wth, int *err, gchar **err_info)
122 t_5VW_Capture_Header Capture_Header;
123 int encap = WTAP_ENCAP_UNKNOWN;
125 errno = WTAP_ERR_CANT_READ;
126 bytes_read = file_read(&Capture_Header.Info_Header, sizeof(t_5VW_Info_Header), wth->fh);
127 if (bytes_read != sizeof(t_5VW_Info_Header)) {
128 *err = file_error(wth->fh, err_info);
129 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
134 /* Check whether that's 5Views format or not */
135 if(Capture_Header.Info_Header.Signature != CST_5VW_INFO_HEADER_KEY)
141 Capture_Header.Info_Header.Version =
142 pletohl(&Capture_Header.Info_Header.Version);
143 switch (Capture_Header.Info_Header.Version) {
145 case CST_5VW_INFO_RECORD_VERSION:
149 *err = WTAP_ERR_UNSUPPORTED;
150 *err_info = g_strdup_printf("5views: header version %u unsupported", Capture_Header.Info_Header.Version);
154 /* Check File Type */
155 Capture_Header.Info_Header.FileType =
156 pletohl(&Capture_Header.Info_Header.FileType);
157 if((Capture_Header.Info_Header.FileType & CST_5VW_CAPTURE_FILE_TYPE_MASK) != CST_5VW_CAPTURE_FILEID)
159 *err = WTAP_ERR_UNSUPPORTED;
160 *err_info = g_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header.Info_Header.Version);
164 /* Check possible Encap */
165 switch (Capture_Header.Info_Header.FileType) {
166 case CST_5VW_CAPTURE_ETH_FILEID:
167 encap = WTAP_ENCAP_ETHERNET;
169 /* case CST_5VW_CAPTURE_WAN_FILEID:
173 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
174 *err_info = g_strdup_printf("5views: network type %u unknown or unsupported",
175 Capture_Header.Info_Header.FileType);
179 /* read the remaining header information */
180 bytes_read = file_read(&Capture_Header.HeaderDateCreation, sizeof (t_5VW_Capture_Header) - sizeof(t_5VW_Info_Header), wth->fh);
181 if (bytes_read != sizeof (t_5VW_Capture_Header)- sizeof(t_5VW_Info_Header) ) {
182 *err = file_error(wth->fh, err_info);
184 *err = WTAP_ERR_SHORT_READ;
188 /* This is a 5views capture file */
189 wth->file_type = WTAP_FILE_5VIEWS;
190 wth->subtype_read = _5views_read;
191 wth->subtype_seek_read = _5views_seek_read;
192 wth->file_encap = encap;
193 wth->snapshot_length = 0; /* not available in header */
194 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
199 /* Read the next packet */
201 _5views_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
203 t_5VW_TimeStamped_Header TimeStamped_Header;
210 bytes_read = _5views_read_header(wth, wth->fh, &TimeStamped_Header, err, err_info);
211 if (bytes_read == -1) {
213 * We failed to read the header.
218 TimeStamped_Header.Key = pletohl(&TimeStamped_Header.Key);
219 if(TimeStamped_Header.Key != CST_5VW_RECORDS_HEADER_KEY) {
220 *err = WTAP_ERR_BAD_FILE;
221 *err_info = g_strdup_printf("5views: Time-stamped header has bad key value 0x%08X",
222 TimeStamped_Header.Key);
226 TimeStamped_Header.RecSubType =
227 pletohl(&TimeStamped_Header.RecSubType);
228 TimeStamped_Header.RecSize =
229 pletohl(&TimeStamped_Header.RecSize);
230 if(TimeStamped_Header.RecSubType != CST_5VW_FRAME_RECORD) {
231 if (file_seek(wth->fh, TimeStamped_Header.RecSize, SEEK_CUR, err) == -1)
237 packet_size = TimeStamped_Header.RecSize;
238 orig_size = TimeStamped_Header.RecSize;
239 if (packet_size > WTAP_MAX_PACKET_SIZE) {
241 * Probably a corrupt capture file; don't blow up trying
242 * to allocate space for an immensely-large packet.
244 *err = WTAP_ERR_BAD_FILE;
245 *err_info = g_strdup_printf("5views: File has %u-byte packet, bigger than maximum of %u",
246 packet_size, WTAP_MAX_PACKET_SIZE);
250 *data_offset = file_tell(wth->fh);
252 buffer_assure_space(wth->frame_buffer, packet_size);
253 if (!_5views_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
254 packet_size, err, err_info))
255 return FALSE; /* Read error */
257 TimeStamped_Header.Utc = pletohl(&TimeStamped_Header.Utc);
258 TimeStamped_Header.NanoSecondes =
259 pletohl(&TimeStamped_Header.NanoSecondes);
260 wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
261 wth->phdr.ts.secs = TimeStamped_Header.Utc;
262 wth->phdr.ts.nsecs = TimeStamped_Header.NanoSecondes;
263 wth->phdr.caplen = packet_size;
264 wth->phdr.len = orig_size;
266 switch (wth->file_encap) {
268 case WTAP_ENCAP_ETHERNET:
269 /* We assume there's no FCS in this frame. */
270 wth->phdr.pseudo_header.eth.fcs_len = 0;
280 _5views_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
285 errno = WTAP_ERR_CANT_READ;
286 bytes_read = file_read(pd, length, fh);
288 if (bytes_read != length) {
289 *err = file_error(fh, err_info);
291 *err = WTAP_ERR_SHORT_READ;
298 /* Read the header of the next packet; if "silent" is TRUE, don't complain
299 to the console, as we're testing to see if the file appears to be of a
302 Return -1 on an error, or the number of bytes of header read on success. */
304 _5views_read_header(wtap *wth _U_, FILE_T fh, t_5VW_TimeStamped_Header *hdr, int *err, gchar **err_info)
306 int bytes_read, bytes_to_read;
308 bytes_to_read = sizeof(t_5VW_TimeStamped_Header);
310 /* Read record header. */
311 bytes_read = file_read(hdr, bytes_to_read, fh);
312 if (bytes_read != bytes_to_read) {
313 *err = file_error(fh, err_info);
314 if (*err == 0 && bytes_read != 0) {
315 *err = WTAP_ERR_SHORT_READ;
324 _5views_seek_read(wtap *wth, gint64 seek_off,
325 struct wtap_pkthdr *phdr, guint8 *pd, int length,
326 int *err, gchar **err_info)
328 union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
329 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
332 * Read the packet data.
334 if (!_5views_read_rec_data(wth->random_fh, pd, length, err, err_info))
337 switch (wth->file_encap) {
339 case WTAP_ENCAP_ETHERNET:
340 /* We assume there's no FCS in this frame. */
341 pseudo_header->eth.fcs_len = 0;
354 static const int wtap_encap[] = {
355 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
356 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ethernet */
358 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
360 /* Returns 0 if we could write the specified encapsulation type,
361 an error indication otherwise. */
362 int _5views_dump_can_write_encap(int encap)
364 /* Per-packet encapsulations aren't supported. */
365 if (encap == WTAP_ENCAP_PER_PACKET)
366 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
368 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
369 return WTAP_ERR_UNSUPPORTED_ENCAP;
374 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
376 gboolean _5views_dump_open(wtap_dumper *wdh, int *err)
378 _5views_dump_t *_5views;
380 /* We can't fill in all the fields in the file header, as we
381 haven't yet written any packets. As we'll have to rewrite
382 the header when we've written out all the packets, we just
383 skip over the header for now. */
384 if (fseek(wdh->fh, sizeof(t_5VW_Capture_Header), SEEK_SET) == -1) {
389 /* This is a 5Views file */
390 wdh->subtype_write = _5views_dump;
391 wdh->subtype_close = _5views_dump_close;
392 _5views = (_5views_dump_t *)g_malloc(sizeof(_5views_dump_t));
393 wdh->priv = (void *)_5views;
394 _5views->nframes = 0;
399 /* Write a record for a packet to a dump file.
400 Returns TRUE on success, FALSE on failure. */
401 static gboolean _5views_dump(wtap_dumper *wdh,
402 const struct wtap_pkthdr *phdr,
403 const guint8 *pd, int *err)
405 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
406 static t_5VW_TimeStamped_Header HeaderFrame;
409 /* constant fields */
410 HeaderFrame.Key = htolel(CST_5VW_RECORDS_HEADER_KEY);
411 HeaderFrame.HeaderSize = htoles(sizeof(t_5VW_TimeStamped_Header));
412 HeaderFrame.HeaderType = htoles(CST_5VW_TIMESTAMPED_HEADER_TYPE);
413 HeaderFrame.RecType = htolel(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
414 HeaderFrame.RecSubType = htolel(CST_5VW_FRAME_RECORD);
415 HeaderFrame.RecNb = htolel(1);
417 /* record-dependant fields */
418 HeaderFrame.Utc = htolel(phdr->ts.secs);
419 HeaderFrame.NanoSecondes = htolel(phdr->ts.nsecs);
420 HeaderFrame.RecSize = htolel(phdr->len);
421 HeaderFrame.RecInfo = htolel(0);
423 /* write the record header */
424 if (!wtap_dump_file_write(wdh, &HeaderFrame,
425 sizeof(t_5VW_TimeStamped_Header), err))
429 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
437 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
439 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
440 t_5VW_Capture_Header file_hdr;
442 if (fseek(wdh->fh, 0, SEEK_SET) == -1) {
447 /* fill in the Info_Header */
448 file_hdr.Info_Header.Signature = htolel(CST_5VW_INFO_HEADER_KEY);
449 file_hdr.Info_Header.Size = htolel(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
450 file_hdr.Info_Header.Version = htolel(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
451 file_hdr.Info_Header.DataSize = htolel(sizeof(t_5VW_Attributes_Header)
453 + sizeof(t_5VW_Attributes_Header)
455 /* Total size of data included in the Info Record (except the header size) */
456 file_hdr.Info_Header.FileType = htolel(wtap_encap[wdh->encap]); /* Type of the file */
457 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
458 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
459 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
461 /* fill in the HeaderDateCreation */
462 file_hdr.HeaderDateCreation.Type = htolel(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
463 file_hdr.HeaderDateCreation.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
464 file_hdr.HeaderDateCreation.Nb = htoles(1); /* Number of elements */
466 /* fill in the Time field */
470 file_hdr.Time = htolel(time(NULL));
472 /* fill in the Time field */
473 file_hdr.HeaderNbFrames.Type = htolel(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
474 file_hdr.HeaderNbFrames.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
475 file_hdr.HeaderNbFrames.Nb = htoles(1); /* Number of elements */
477 /* fill in the number of frames saved */
478 file_hdr.TramesStockeesInFile = htolel(_5views->nframes);
480 /* Write the file header. */
481 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof(t_5VW_Capture_Header),