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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "file_wrappers.h"
39 guint32 Size; /* Total size of Header in bytes (included Signature) */
40 guint32 Version; /* Identify version and so the format of this record */
41 guint32 DataSize; /* Total size of data included in the Info Record (except the header size) */
42 guint32 FileType; /* Type of the file */
43 guint32 Reserved[3]; /* Reserved for future use */
48 guint32 Type; /* Id of the attribute */
49 guint16 Size; /* Size of the data part of the attribute (not including header size) */
50 guint16 Nb; /* Number of elements */
51 }t_5VW_Attributes_Header;
54 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAAU /* signature */
56 #define CST_5VW_INFO_RECORD_VERSION 0x00010000U /* version */
58 #define CST_5VW_DECALE_FILE_TYPE 24
59 #define CST_5VW_SECTION_CAPTURES 0x08U
60 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
61 #define CST_5VW_FLAT_FILE 0x10000000U
62 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
63 #define CST_5VW_FAMILY_CAP_ETH 0x01U
64 #define CST_5VW_FAMILY_CAP_WAN 0x02U
65 #define CST_5VW_DECALE_FILE_FAMILY 12
66 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
67 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
68 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
69 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
71 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000U
73 #define CST_5VW_FRAME_RECORD 0x00000000U
74 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEEU
78 t_5VW_Info_Header Info_Header;
79 t_5VW_Attributes_Header HeaderDateCreation;
81 t_5VW_Attributes_Header HeaderNbFrames;
82 guint32 TramesStockeesInFile;
83 }t_5VW_Capture_Header;
87 guint32 Key; /* 0x3333EEEE */
88 guint16 HeaderSize; /* Actual size of this header in bytes (32) */
89 guint16 HeaderType; /* Exact type of this header (0x4000) */
90 guint32 RecType; /* Type of record */
91 guint32 RecSubType; /* Subtype of record */
92 guint32 RecSize; /* Size of one record */
93 guint32 RecNb; /* Number of records */
96 guint32 RecInfo; /* Info about Alarm / Event / Frame captured */
97 }t_5VW_TimeStamped_Header;
100 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000U
101 #define CST_5VW_IA_DATE_CREATION 0x80000007U /* Struct t_Attrib_Date_Create */
102 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000U
103 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
104 #define CST_5VW_SYSTEM_RECORD 0x00000000U
106 static gboolean _5views_read(wtap *wth, int *err, gchar **err_info,
107 gint64 *data_offset);
108 static gboolean _5views_read_rec_data(FILE_T fh, guint8 *pd, int length,
109 int *err, gchar **err_info);
110 static int _5views_read_header(wtap *wth, FILE_T fh,
111 t_5VW_TimeStamped_Header *hdr, int *err, gchar **err_info);
112 static gboolean _5views_seek_read(wtap *wth, gint64 seek_off,
113 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
114 int *err, gchar **err_info);
117 static gboolean _5views_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
118 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err);
119 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err);
122 int _5views_open(wtap *wth, int *err, gchar **err_info)
125 t_5VW_Capture_Header Capture_Header;
126 int encap = WTAP_ENCAP_UNKNOWN;
128 errno = WTAP_ERR_CANT_READ;
129 bytes_read = file_read(&Capture_Header.Info_Header, sizeof(t_5VW_Info_Header), wth->fh);
130 if (bytes_read != sizeof(t_5VW_Info_Header)) {
131 *err = file_error(wth->fh, err_info);
137 wth->data_offset+=bytes_read;
139 /* Check whether that's 5Views format or not */
140 if(Capture_Header.Info_Header.Signature != CST_5VW_INFO_HEADER_KEY)
146 Capture_Header.Info_Header.Version =
147 pletohl(&Capture_Header.Info_Header.Version);
148 switch (Capture_Header.Info_Header.Version) {
150 case CST_5VW_INFO_RECORD_VERSION:
154 *err = WTAP_ERR_UNSUPPORTED;
155 *err_info = g_strdup_printf("5views: header version %u unsupported", Capture_Header.Info_Header.Version);
159 /* Check File Type */
160 Capture_Header.Info_Header.FileType =
161 pletohl(&Capture_Header.Info_Header.FileType);
162 if((Capture_Header.Info_Header.FileType & CST_5VW_CAPTURE_FILE_TYPE_MASK) != CST_5VW_CAPTURE_FILEID)
164 *err = WTAP_ERR_UNSUPPORTED;
165 *err_info = g_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header.Info_Header.Version);
169 /* Check possible Encap */
170 switch (Capture_Header.Info_Header.FileType) {
171 case CST_5VW_CAPTURE_ETH_FILEID:
172 encap = WTAP_ENCAP_ETHERNET;
174 /* case CST_5VW_CAPTURE_WAN_FILEID:
178 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
179 *err_info = g_strdup_printf("5views: network type %u unknown or unsupported",
180 Capture_Header.Info_Header.FileType);
184 /* read the remaining header information */
185 bytes_read = file_read(&Capture_Header.HeaderDateCreation, sizeof (t_5VW_Capture_Header) - sizeof(t_5VW_Info_Header), wth->fh);
186 if (bytes_read != sizeof (t_5VW_Capture_Header)- sizeof(t_5VW_Info_Header) ) {
187 *err = file_error(wth->fh, err_info);
192 wth->data_offset+=bytes_read;
194 /* This is a 5views capture file */
195 wth->file_type = WTAP_FILE_5VIEWS;
196 wth->subtype_read = _5views_read;
197 wth->subtype_seek_read = _5views_seek_read;
198 wth->file_encap = encap;
199 wth->snapshot_length = 0; /* not available in header */
200 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
205 /* Read the next packet */
207 _5views_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
209 t_5VW_TimeStamped_Header TimeStamped_Header;
216 bytes_read = _5views_read_header(wth, wth->fh, &TimeStamped_Header, err, err_info);
217 if (bytes_read == -1) {
219 * We failed to read the header.
223 wth->data_offset += bytes_read;
225 TimeStamped_Header.Key = pletohl(&TimeStamped_Header.Key);
226 if(TimeStamped_Header.Key != CST_5VW_RECORDS_HEADER_KEY)
229 TimeStamped_Header.RecSubType =
230 pletohl(&TimeStamped_Header.RecSubType);
231 TimeStamped_Header.RecSize =
232 pletohl(&TimeStamped_Header.RecSize);
233 if(TimeStamped_Header.RecSubType != CST_5VW_FRAME_RECORD) {
234 if (file_seek(wth->fh, TimeStamped_Header.RecSize, SEEK_CUR, err) == -1)
236 wth->data_offset += TimeStamped_Header.RecSize;
241 packet_size = TimeStamped_Header.RecSize;
242 orig_size = TimeStamped_Header.RecSize;
244 *data_offset = wth->data_offset;
246 buffer_assure_space(wth->frame_buffer, packet_size);
247 if (!_5views_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
248 packet_size, err, err_info))
249 return FALSE; /* Read error */
251 wth->data_offset += packet_size;
252 TimeStamped_Header.Utc = pletohl(&TimeStamped_Header.Utc);
253 TimeStamped_Header.NanoSecondes =
254 pletohl(&TimeStamped_Header.NanoSecondes);
255 wth->phdr.ts.secs = TimeStamped_Header.Utc;
256 wth->phdr.ts.nsecs = TimeStamped_Header.NanoSecondes;
257 wth->phdr.caplen = packet_size;
258 wth->phdr.len = orig_size;
260 switch (wth->file_encap) {
262 case WTAP_ENCAP_ETHERNET:
263 /* We assume there's no FCS in this frame. */
264 wth->pseudo_header.eth.fcs_len = 0;
274 _5views_read_rec_data(FILE_T fh, guint8 *pd, int length, int *err,
279 errno = WTAP_ERR_CANT_READ;
280 bytes_read = file_read(pd, length, fh);
282 if (bytes_read != length) {
283 *err = file_error(fh, err_info);
285 *err = WTAP_ERR_SHORT_READ;
292 /* Read the header of the next packet; if "silent" is TRUE, don't complain
293 to the console, as we're testing to see if the file appears to be of a
296 Return -1 on an error, or the number of bytes of header read on success. */
298 _5views_read_header(wtap *wth _U_, FILE_T fh, t_5VW_TimeStamped_Header *hdr, int *err, gchar **err_info)
300 int bytes_read, bytes_to_read;
302 bytes_to_read = sizeof(t_5VW_TimeStamped_Header);
304 /* Read record header. */
305 bytes_read = file_read(hdr, bytes_to_read, fh);
306 if (bytes_read != bytes_to_read) {
307 *err = file_error(fh, err_info);
308 if (*err == 0 && bytes_read != 0) {
309 *err = WTAP_ERR_SHORT_READ;
318 _5views_seek_read(wtap *wth, gint64 seek_off,
319 union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
320 int *err, gchar **err_info)
322 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
325 * Read the packet data.
327 if (!_5views_read_rec_data(wth->random_fh, pd, length, err, err_info))
330 switch (wth->file_encap) {
332 case WTAP_ENCAP_ETHERNET:
333 /* We assume there's no FCS in this frame. */
334 pseudo_header->eth.fcs_len = 0;
347 static const int wtap_encap[] = {
348 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
349 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ehernet Ethernet */
350 -1, /* WTAP_ENCAP_TOKEN_RING -> unsupported */
351 -1, /* WTAP_ENCAP_SLIP -> unsupported */
352 -1, /* WTAP_ENCAP_PPP -> unsupported */
353 -1, /* WTAP_ENCAP_FDDI -> unsupported */
354 -1, /* WTAP_ENCAP_FDDI_BITSWAPPED -> unsupported */
355 -1, /* WTAP_ENCAP_RAW_IP -> unsupported */
356 -1, /* WTAP_ENCAP_ARCNET -> unsupported */
357 -1, /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
358 -1, /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
359 -1, /* WTAP_ENCAP_LAPB -> unsupported */
360 -1, /* WTAP_ENCAP_ATM_PDUS -> unsupported */
361 -1 /* WTAP_ENCAP_NULL -> unsupported */
363 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
365 /* Returns 0 if we could write the specified encapsulation type,
366 an error indication otherwise. */
367 int _5views_dump_can_write_encap(int encap)
369 /* Per-packet encapsulations aren't supported. */
370 if (encap == WTAP_ENCAP_PER_PACKET)
371 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
373 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
374 return WTAP_ERR_UNSUPPORTED_ENCAP;
379 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
381 gboolean _5views_dump_open(wtap_dumper *wdh, int *err)
383 _5views_dump_t *_5views;
385 /* We can't fill in all the fields in the file header, as we
386 haven't yet written any packets. As we'll have to rewrite
387 the header when we've written out all the packets, we just
388 skip over the header for now. */
389 if (fseek(wdh->fh, sizeof(t_5VW_Capture_Header), SEEK_SET) == -1) {
394 /* This is a 5Views file */
395 wdh->subtype_write = _5views_dump;
396 wdh->subtype_close = _5views_dump_close;
397 _5views = (_5views_dump_t *)g_malloc(sizeof(_5views_dump_t));
398 wdh->priv = (void *)_5views;
399 _5views->nframes = 0;
404 /* Write a record for a packet to a dump file.
405 Returns TRUE on success, FALSE on failure. */
406 static gboolean _5views_dump(wtap_dumper *wdh,
407 const struct wtap_pkthdr *phdr,
408 const union wtap_pseudo_header *pseudo_header _U_,
409 const guint8 *pd, int *err)
411 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
412 static t_5VW_TimeStamped_Header HeaderFrame;
415 /* constant fields */
416 HeaderFrame.Key = htolel(CST_5VW_RECORDS_HEADER_KEY);
417 HeaderFrame.HeaderSize = htoles(sizeof(t_5VW_TimeStamped_Header));
418 HeaderFrame.HeaderType = htoles(CST_5VW_TIMESTAMPED_HEADER_TYPE);
419 HeaderFrame.RecType = htolel(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
420 HeaderFrame.RecSubType = htolel(CST_5VW_FRAME_RECORD);
421 HeaderFrame.RecNb = htolel(1);
423 /* record-dependant fields */
424 HeaderFrame.Utc = htolel(phdr->ts.secs);
425 HeaderFrame.NanoSecondes = htolel(phdr->ts.nsecs);
426 HeaderFrame.RecSize = htolel(phdr->len);
427 HeaderFrame.RecInfo = htolel(0);
429 /* write the record header */
430 if (!wtap_dump_file_write(wdh, &HeaderFrame,
431 sizeof(t_5VW_TimeStamped_Header), err))
435 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
443 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
445 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
446 t_5VW_Capture_Header file_hdr;
448 if (fseek(wdh->fh, 0, SEEK_SET) == -1) {
453 /* fill in the Info_Header */
454 file_hdr.Info_Header.Signature = htolel(CST_5VW_INFO_HEADER_KEY);
455 file_hdr.Info_Header.Size = htolel(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
456 file_hdr.Info_Header.Version = htolel(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
457 file_hdr.Info_Header.DataSize = htolel(sizeof(t_5VW_Attributes_Header)
459 + sizeof(t_5VW_Attributes_Header)
461 /* Total size of data included in the Info Record (except the header size) */
462 file_hdr.Info_Header.FileType = htolel(wtap_encap[wdh->encap]); /* Type of the file */
463 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
464 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
465 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
467 /* fill in the HeaderDateCreation */
468 file_hdr.HeaderDateCreation.Type = htolel(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
469 file_hdr.HeaderDateCreation.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
470 file_hdr.HeaderDateCreation.Nb = htoles(1); /* Number of elements */
472 /* fill in the Time field */
476 file_hdr.Time = htolel(time(NULL));
478 /* fill in the Time field */
479 file_hdr.HeaderNbFrames.Type = htolel(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
480 file_hdr.HeaderNbFrames.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
481 file_hdr.HeaderNbFrames.Nb = htoles(1); /* Number of elements */
483 /* fill in the number of frames saved */
484 file_hdr.TramesStockeesInFile = htolel(_5views->nframes);
486 /* Write the file header. */
487 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof(t_5VW_Capture_Header),