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 0xAAAAAAAA /* signature */
56 #define CST_5VW_INFO_RECORD_VERSION 0x00010000 /* version */
58 #define CST_5VW_DECALE_FILE_TYPE 24
59 #define CST_5VW_SECTION_CAPTURES 0x08
60 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
61 #define CST_5VW_FLAT_FILE 0x10000000
62 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
63 #define CST_5VW_FAMILY_CAP_ETH 0x01
64 #define CST_5VW_FAMILY_CAP_WAN 0x02
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 0xFF000000
73 #define CST_5VW_FRAME_RECORD 0x00000000
74 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEE
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 0x20000000
101 #define CST_5VW_IA_DATE_CREATION 0x80000007 /* Struct t_Attrib_Date_Create */
102 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000
103 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
104 #define CST_5VW_SYSTEM_RECORD 0x00000000
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, 1, 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, 1, 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_SET, 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, 1, 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, 1, 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;
342 static const int wtap_encap[] = {
343 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
344 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ehernet Ethernet */
345 -1, /* WTAP_ENCAP_TOKEN_RING -> unsupported */
346 -1, /* WTAP_ENCAP_SLIP -> unsupported */
347 -1, /* WTAP_ENCAP_PPP -> unsupported */
348 -1, /* WTAP_ENCAP_FDDI -> unsupported */
349 -1, /* WTAP_ENCAP_FDDI_BITSWAPPED -> unsupported */
350 -1, /* WTAP_ENCAP_RAW_IP -> unsupported */
351 -1, /* WTAP_ENCAP_ARCNET -> unsupported */
352 -1, /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
353 -1, /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
354 -1, /* WTAP_ENCAP_LAPB -> unsupported */
355 -1, /* WTAP_ENCAP_ATM_PDUS -> unsupported */
356 -1 /* WTAP_ENCAP_NULL -> unsupported */
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, gboolean cant_seek _U_, int *err)
379 /* We can't fill in all the fields in the file header, as we
380 haven't yet written any packets. As we'll have to rewrite
381 the header when we've written out all the packets, we just
382 skip over the header for now. */
383 if (fseek(wdh->fh, sizeof(t_5VW_Capture_Header), SEEK_SET) == -1) {
388 /* This is a 5Views file */
389 wdh->subtype_write = _5views_dump;
390 wdh->subtype_close = _5views_dump_close;
391 wdh->dump._5views = g_malloc(sizeof(_5views_dump_t));
392 wdh->dump._5views->nframes = 0;
397 /* Write a record for a packet to a dump file.
398 Returns TRUE on success, FALSE on failure. */
399 static gboolean _5views_dump(wtap_dumper *wdh,
400 const struct wtap_pkthdr *phdr,
401 const union wtap_pseudo_header *pseudo_header _U_,
402 const guchar *pd, int *err)
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 nwritten = fwrite(&HeaderFrame, 1, sizeof(t_5VW_TimeStamped_Header), wdh->fh);
425 if (nwritten != sizeof(t_5VW_TimeStamped_Header)) {
426 if (nwritten == 0 && ferror(wdh->fh))
429 *err = WTAP_ERR_SHORT_WRITE;
434 nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
435 if (nwritten != phdr->caplen) {
436 if (nwritten == 0 && ferror(wdh->fh))
439 *err = WTAP_ERR_SHORT_WRITE;
443 wdh->dump._5views->nframes ++;
448 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
450 t_5VW_Capture_Header file_hdr;
453 if (fseek(wdh->fh, 0, SEEK_SET) == -1) {
458 /* fill in the Info_Header */
459 file_hdr.Info_Header.Signature = htolel(CST_5VW_INFO_HEADER_KEY);
460 file_hdr.Info_Header.Size = htolel(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
461 file_hdr.Info_Header.Version = htolel(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
462 file_hdr.Info_Header.DataSize = htolel(sizeof(t_5VW_Attributes_Header)
464 + sizeof(t_5VW_Attributes_Header)
466 /* Total size of data included in the Info Record (except the header size) */
467 file_hdr.Info_Header.FileType = htolel(wtap_encap[wdh->encap]); /* Type of the file */
468 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
469 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
470 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
472 /* fill in the HeaderDateCreation */
473 file_hdr.HeaderDateCreation.Type = htolel(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
474 file_hdr.HeaderDateCreation.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
475 file_hdr.HeaderDateCreation.Nb = htoles(1); /* Number of elements */
477 /* fill in the Time field */
481 file_hdr.Time = htolel(time(NULL));
483 /* fill in the Time field */
484 file_hdr.HeaderNbFrames.Type = htolel(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
485 file_hdr.HeaderNbFrames.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
486 file_hdr.HeaderNbFrames.Nb = htoles(1); /* Number of elements */
488 /* fill in the number of frames saved */
489 file_hdr.TramesStockeesInFile = htolel(wdh->dump._5views->nframes);
491 /* Write the file header. */
492 nwritten = fwrite(&file_hdr, 1, sizeof(t_5VW_Capture_Header), wdh->fh);
493 if (nwritten != sizeof(t_5VW_Capture_Header)) {
494 if (nwritten == 0 && ferror(wdh->fh))
497 *err = WTAP_ERR_SHORT_WRITE;