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, guchar *pd, int length,
110 static int _5views_read_header(wtap *wth, FILE_T fh,
111 t_5VW_TimeStamped_Header *hdr, int *err);
112 static gboolean _5views_seek_read(wtap *wth, gint64 seek_off,
113 union wtap_pseudo_header *pseudo_header, guchar *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 guchar *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);
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);
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 _U_, gint64 *data_offset)
209 t_5VW_TimeStamped_Header TimeStamped_Header;
216 bytes_read = _5views_read_header(wth, wth->fh, &TimeStamped_Header, err);
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),
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, guchar *pd, int length, int *err)
278 errno = WTAP_ERR_CANT_READ;
279 bytes_read = file_read(pd, length, fh);
281 if (bytes_read != length) {
282 *err = file_error(fh);
284 *err = WTAP_ERR_SHORT_READ;
291 /* Read the header of the next packet; if "silent" is TRUE, don't complain
292 to the console, as we're testing to see if the file appears to be of a
295 Return -1 on an error, or the number of bytes of header read on success. */
297 _5views_read_header(wtap *wth _U_, FILE_T fh, t_5VW_TimeStamped_Header *hdr, int *err)
299 int bytes_read, bytes_to_read;
301 bytes_to_read = sizeof(t_5VW_TimeStamped_Header);
303 /* Read record header. */
304 bytes_read = file_read(hdr, bytes_to_read, fh);
305 if (bytes_read != bytes_to_read) {
306 *err = file_error(fh);
307 if (*err == 0 && bytes_read != 0) {
308 *err = WTAP_ERR_SHORT_READ;
317 _5views_seek_read(wtap *wth, gint64 seek_off,
318 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
319 int *err, gchar **err_info _U_)
321 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
324 * Read the packet data.
326 if (!_5views_read_rec_data(wth->random_fh, pd, length, err))
329 switch (wth->file_encap) {
331 case WTAP_ENCAP_ETHERNET:
332 /* We assume there's no FCS in this frame. */
333 pseudo_header->eth.fcs_len = 0;
346 static const int wtap_encap[] = {
347 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
348 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ehernet Ethernet */
349 -1, /* WTAP_ENCAP_TOKEN_RING -> unsupported */
350 -1, /* WTAP_ENCAP_SLIP -> unsupported */
351 -1, /* WTAP_ENCAP_PPP -> unsupported */
352 -1, /* WTAP_ENCAP_FDDI -> unsupported */
353 -1, /* WTAP_ENCAP_FDDI_BITSWAPPED -> unsupported */
354 -1, /* WTAP_ENCAP_RAW_IP -> unsupported */
355 -1, /* WTAP_ENCAP_ARCNET -> unsupported */
356 -1, /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
357 -1, /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
358 -1, /* WTAP_ENCAP_LAPB -> unsupported */
359 -1, /* WTAP_ENCAP_ATM_PDUS -> unsupported */
360 -1 /* WTAP_ENCAP_NULL -> unsupported */
362 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
364 /* Returns 0 if we could write the specified encapsulation type,
365 an error indication otherwise. */
366 int _5views_dump_can_write_encap(int encap)
368 /* Per-packet encapsulations aren't supported. */
369 if (encap == WTAP_ENCAP_PER_PACKET)
370 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
372 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
373 return WTAP_ERR_UNSUPPORTED_ENCAP;
378 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
380 gboolean _5views_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
382 _5views_dump_t *_5views;
384 /* This is a 5Views file. We can't fill in some fields in the
385 header until all the packets have been written, so we can't
388 *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
392 /* We can't fill in all the fields in the file header, as we
393 haven't yet written any packets. As we'll have to rewrite
394 the header when we've written out all the packets, we just
395 skip over the header for now. */
396 if (fseek(wdh->fh, sizeof(t_5VW_Capture_Header), SEEK_SET) == -1) {
401 /* This is a 5Views file */
402 wdh->subtype_write = _5views_dump;
403 wdh->subtype_close = _5views_dump_close;
404 _5views = (_5views_dump_t *)g_malloc(sizeof(_5views_dump_t));
405 wdh->priv = (void *)_5views;
406 _5views->nframes = 0;
411 /* Write a record for a packet to a dump file.
412 Returns TRUE on success, FALSE on failure. */
413 static gboolean _5views_dump(wtap_dumper *wdh,
414 const struct wtap_pkthdr *phdr,
415 const union wtap_pseudo_header *pseudo_header _U_,
416 const guchar *pd, int *err)
418 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
419 static t_5VW_TimeStamped_Header HeaderFrame;
422 /* constant fields */
423 HeaderFrame.Key = htolel(CST_5VW_RECORDS_HEADER_KEY);
424 HeaderFrame.HeaderSize = htoles(sizeof(t_5VW_TimeStamped_Header));
425 HeaderFrame.HeaderType = htoles(CST_5VW_TIMESTAMPED_HEADER_TYPE);
426 HeaderFrame.RecType = htolel(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
427 HeaderFrame.RecSubType = htolel(CST_5VW_FRAME_RECORD);
428 HeaderFrame.RecNb = htolel(1);
430 /* record-dependant fields */
431 HeaderFrame.Utc = htolel(phdr->ts.secs);
432 HeaderFrame.NanoSecondes = htolel(phdr->ts.nsecs);
433 HeaderFrame.RecSize = htolel(phdr->len);
434 HeaderFrame.RecInfo = htolel(0);
436 /* write the record header */
437 if (!wtap_dump_file_write(wdh, &HeaderFrame,
438 sizeof(t_5VW_TimeStamped_Header), err))
442 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
450 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
452 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
453 t_5VW_Capture_Header file_hdr;
455 if (fseek(wdh->fh, 0, SEEK_SET) == -1) {
460 /* fill in the Info_Header */
461 file_hdr.Info_Header.Signature = htolel(CST_5VW_INFO_HEADER_KEY);
462 file_hdr.Info_Header.Size = htolel(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
463 file_hdr.Info_Header.Version = htolel(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
464 file_hdr.Info_Header.DataSize = htolel(sizeof(t_5VW_Attributes_Header)
466 + sizeof(t_5VW_Attributes_Header)
468 /* Total size of data included in the Info Record (except the header size) */
469 file_hdr.Info_Header.FileType = htolel(wtap_encap[wdh->encap]); /* Type of the file */
470 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
471 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
472 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
474 /* fill in the HeaderDateCreation */
475 file_hdr.HeaderDateCreation.Type = htolel(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
476 file_hdr.HeaderDateCreation.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
477 file_hdr.HeaderDateCreation.Nb = htoles(1); /* Number of elements */
479 /* fill in the Time field */
483 file_hdr.Time = htolel(time(NULL));
485 /* fill in the Time field */
486 file_hdr.HeaderNbFrames.Type = htolel(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
487 file_hdr.HeaderNbFrames.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
488 file_hdr.HeaderNbFrames.Nb = htoles(1); /* Number of elements */
490 /* fill in the number of frames saved */
491 file_hdr.TramesStockeesInFile = htolel(_5views->nframes);
493 /* Write the file header. */
494 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof(t_5VW_Capture_Header),