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"
38 guint32 Size; /* Total size of Header in bytes (included Signature) */
39 guint32 Version; /* Identify version and so the format of this record */
40 guint32 DataSize; /* Total size of data included in the Info Record (except the header size) */
41 guint32 FileType; /* Type of the file */
42 guint32 Reserved[3]; /* Reserved for future use */
47 guint32 Type; /* Id of the attribute */
48 guint16 Size; /* Size of the data part of the attribute (not including header size) */
49 guint16 Nb; /* Number of elements */
50 }t_5VW_Attributes_Header;
53 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAA /* signature */
55 #define CST_5VW_INFO_RECORD_VERSION 0x00010000 /* version */
57 #define CST_5VW_DECALE_FILE_TYPE 24
58 #define CST_5VW_SECTION_CAPTURES 0x08
59 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
60 #define CST_5VW_FLAT_FILE 0x10000000
61 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
62 #define CST_5VW_FAMILY_CAP_ETH 0x01
63 #define CST_5VW_FAMILY_CAP_WAN 0x02
64 #define CST_5VW_DECALE_FILE_FAMILY 12
65 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
66 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
67 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
68 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
70 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000
72 #define CST_5VW_FRAME_RECORD 0x00000000
73 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEE
77 t_5VW_Info_Header Info_Header;
78 t_5VW_Attributes_Header HeaderDateCreation;
80 t_5VW_Attributes_Header HeaderNbFrames;
81 guint32 TramesStockeesInFile;
82 }t_5VW_Capture_Header;
86 guint32 Key; /* 0x3333EEEE */
87 guint16 HeaderSize; /* Actual size of this header in bytes (32) */
88 guint16 HeaderType; /* Exact type of this header (0x4000) */
89 guint32 RecType; /* Type of record */
90 guint32 RecSubType; /* Subtype of record */
91 guint32 RecSize; /* Size of one record */
92 guint32 RecNb; /* Number of records */
95 guint32 RecInfo; /* Info about Alarm / Event / Frame captured */
96 }t_5VW_TimeStamped_Header;
99 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000
100 #define CST_5VW_IA_DATE_CREATION 0x80000007 /* Struct t_Attrib_Date_Create */
101 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000
102 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
103 #define CST_5VW_SYSTEM_RECORD 0x00000000
105 static gboolean _5views_read(wtap *wth, int *err, gchar **err_info,
107 static gboolean _5views_read_rec_data(FILE_T fh, guchar *pd, int length,
109 static int _5views_read_header(wtap *wth, FILE_T fh,
110 t_5VW_TimeStamped_Header *hdr, int *err);
111 static gboolean _5views_seek_read(wtap *wth, long seek_off,
112 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
113 int *err, gchar **err_info);
116 static gboolean _5views_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
117 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
118 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err);
121 int _5views_open(wtap *wth, int *err, gchar **err_info)
124 t_5VW_Capture_Header Capture_Header;
125 int encap = WTAP_ENCAP_UNKNOWN;
127 errno = WTAP_ERR_CANT_READ;
128 bytes_read = file_read(&Capture_Header.Info_Header, 1, sizeof(t_5VW_Info_Header), wth->fh);
129 if (bytes_read != sizeof(t_5VW_Info_Header)) {
130 *err = file_error(wth->fh);
136 wth->data_offset+=bytes_read;
138 /* Check whether that's 5Views format or not */
139 if(Capture_Header.Info_Header.Signature != CST_5VW_INFO_HEADER_KEY)
145 Capture_Header.Info_Header.Version =
146 pletohl(&Capture_Header.Info_Header.Version);
147 switch (Capture_Header.Info_Header.Version) {
149 case CST_5VW_INFO_RECORD_VERSION:
153 *err = WTAP_ERR_UNSUPPORTED;
154 *err_info = g_strdup_printf("5views: header version %u unsupported", Capture_Header.Info_Header.Version);
158 /* Check File Type */
159 Capture_Header.Info_Header.FileType =
160 pletohl(&Capture_Header.Info_Header.FileType);
161 if((Capture_Header.Info_Header.FileType & CST_5VW_CAPTURE_FILE_TYPE_MASK) != CST_5VW_CAPTURE_FILEID)
163 *err = WTAP_ERR_UNSUPPORTED;
164 *err_info = g_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header.Info_Header.Version);
168 /* Check possible Encap */
169 switch (Capture_Header.Info_Header.FileType) {
170 case CST_5VW_CAPTURE_ETH_FILEID:
171 encap = WTAP_ENCAP_ETHERNET;
173 /* case CST_5VW_CAPTURE_WAN_FILEID:
177 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
178 *err_info = g_strdup_printf("5views: network type %u unknown or unsupported",
179 Capture_Header.Info_Header.FileType);
183 /* read the remaining header information */
184 bytes_read = file_read(&Capture_Header.HeaderDateCreation, 1, sizeof (t_5VW_Capture_Header) - sizeof(t_5VW_Info_Header), wth->fh);
185 if (bytes_read != sizeof (t_5VW_Capture_Header)- sizeof(t_5VW_Info_Header) ) {
186 *err = file_error(wth->fh);
191 wth->data_offset+=bytes_read;
193 /* This is a 5views capture file */
194 wth->file_type = WTAP_FILE_5VIEWS;
195 wth->subtype_read = _5views_read;
196 wth->subtype_seek_read = _5views_seek_read;
197 wth->file_encap = encap;
198 wth->snapshot_length = 0; /* not available in header */
203 /* Read the next packet */
205 _5views_read(wtap *wth, int *err, gchar **err_info _U_, long *data_offset)
207 t_5VW_TimeStamped_Header TimeStamped_Header;
214 bytes_read = _5views_read_header(wth, wth->fh, &TimeStamped_Header, err);
215 if (bytes_read == -1) {
217 * We failed to read the header.
221 wth->data_offset += bytes_read;
223 TimeStamped_Header.Key = pletohl(&TimeStamped_Header.Key);
224 if(TimeStamped_Header.Key != CST_5VW_RECORDS_HEADER_KEY)
227 TimeStamped_Header.RecSubType =
228 pletohl(&TimeStamped_Header.RecSubType);
229 TimeStamped_Header.RecSize =
230 pletohl(&TimeStamped_Header.RecSize);
231 if(TimeStamped_Header.RecSubType != CST_5VW_FRAME_RECORD) {
232 if (file_seek(wth->fh, TimeStamped_Header.RecSize, SEEK_SET, err) == -1)
234 wth->data_offset += TimeStamped_Header.RecSize;
239 packet_size = TimeStamped_Header.RecSize;
240 orig_size = TimeStamped_Header.RecSize;
242 *data_offset = wth->data_offset;
244 buffer_assure_space(wth->frame_buffer, packet_size);
245 if (!_5views_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
247 return FALSE; /* Read error */
249 wth->data_offset += packet_size;
250 TimeStamped_Header.Utc = pletohl(&TimeStamped_Header.Utc);
251 TimeStamped_Header.NanoSecondes =
252 pletohl(&TimeStamped_Header.NanoSecondes);
253 wth->phdr.ts.tv_sec = TimeStamped_Header.Utc;
254 wth->phdr.ts.tv_usec = TimeStamped_Header.NanoSecondes/1000;
255 wth->phdr.caplen = packet_size;
256 wth->phdr.len = orig_size;
258 switch (wth->file_encap) {
260 case WTAP_ENCAP_ETHERNET:
261 /* We assume there's no FCS in this frame. */
262 wth->pseudo_header.eth.fcs_len = 0;
272 _5views_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
276 errno = WTAP_ERR_CANT_READ;
277 bytes_read = file_read(pd, 1, length, fh);
279 if (bytes_read != length) {
280 *err = file_error(fh);
282 *err = WTAP_ERR_SHORT_READ;
289 /* Read the header of the next packet; if "silent" is TRUE, don't complain
290 to the console, as we're testing to see if the file appears to be of a
293 Return -1 on an error, or the number of bytes of header read on success. */
295 _5views_read_header(wtap *wth _U_, FILE_T fh, t_5VW_TimeStamped_Header *hdr, int *err)
297 int bytes_read, bytes_to_read;
299 bytes_to_read = sizeof(t_5VW_TimeStamped_Header);
301 /* Read record header. */
302 bytes_read = file_read(hdr, 1, bytes_to_read, fh);
303 if (bytes_read != bytes_to_read) {
304 *err = file_error(fh);
305 if (*err == 0 && bytes_read != 0) {
306 *err = WTAP_ERR_SHORT_READ;
315 _5views_seek_read(wtap *wth, long seek_off,
316 union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
317 int *err, gchar **err_info _U_)
319 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
322 * Read the packet data.
324 if (!_5views_read_rec_data(wth->random_fh, pd, length, err))
327 switch (wth->file_encap) {
329 case WTAP_ENCAP_ETHERNET:
330 /* We assume there's no FCS in this frame. */
331 pseudo_header->eth.fcs_len = 0;
340 static const int wtap_encap[] = {
341 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
342 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ehernet Ethernet */
343 -1, /* WTAP_ENCAP_TOKEN_RING -> unsupported */
344 -1, /* WTAP_ENCAP_SLIP -> unsupported */
345 -1, /* WTAP_ENCAP_PPP -> unsupported */
346 -1, /* WTAP_ENCAP_FDDI -> unsupported */
347 -1, /* WTAP_ENCAP_FDDI_BITSWAPPED -> unsupported */
348 -1, /* WTAP_ENCAP_RAW_IP -> unsupported */
349 -1, /* WTAP_ENCAP_ARCNET -> unsupported */
350 -1, /* WTAP_ENCAP_ATM_RFC1483 -> unsupported */
351 -1, /* WTAP_ENCAP_LINUX_ATM_CLIP -> unsupported */
352 -1, /* WTAP_ENCAP_LAPB -> unsupported */
353 -1, /* WTAP_ENCAP_ATM_PDUS -> unsupported */
354 -1 /* WTAP_ENCAP_NULL -> unsupported */
356 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
358 /* Returns 0 if we could write the specified encapsulation type,
359 an error indication otherwise. */
360 int _5views_dump_can_write_encap(int encap)
362 /* Per-packet encapsulations aren't supported. */
363 if (encap == WTAP_ENCAP_PER_PACKET)
364 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
366 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
367 return WTAP_ERR_UNSUPPORTED_ENCAP;
372 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
374 gboolean _5views_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
377 /* We can't fill in all the fields in the file header, as we
378 haven't yet written any packets. As we'll have to rewrite
379 the header when we've written out all the packets, we just
380 skip over the header for now. */
381 if (fseek(wdh->fh, sizeof(t_5VW_Capture_Header), SEEK_SET) == -1) {
386 /* This is a 5Views file */
387 wdh->subtype_write = _5views_dump;
388 wdh->subtype_close = _5views_dump_close;
389 wdh->dump._5views = g_malloc(sizeof(_5views_dump_t));
390 wdh->dump._5views->nframes = 0;
395 /* Write a record for a packet to a dump file.
396 Returns TRUE on success, FALSE on failure. */
397 static gboolean _5views_dump(wtap_dumper *wdh,
398 const struct wtap_pkthdr *phdr,
399 const union wtap_pseudo_header *pseudo_header _U_,
400 const guchar *pd, int *err)
404 static t_5VW_TimeStamped_Header HeaderFrame;
407 /* constant fields */
408 HeaderFrame.Key = htolel(CST_5VW_RECORDS_HEADER_KEY);
409 HeaderFrame.HeaderSize = htoles(sizeof(t_5VW_TimeStamped_Header));
410 HeaderFrame.HeaderType = htoles(CST_5VW_TIMESTAMPED_HEADER_TYPE);
411 HeaderFrame.RecType = htolel(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
412 HeaderFrame.RecSubType = htolel(CST_5VW_FRAME_RECORD);
413 HeaderFrame.RecNb = htolel(1);
415 /* record-dependant fields */
416 HeaderFrame.Utc = htolel(phdr->ts.tv_sec);
417 HeaderFrame.NanoSecondes = htolel(phdr->ts.tv_usec*1000);
418 HeaderFrame.RecSize = htolel(phdr->len);
419 HeaderFrame.RecInfo = htolel(0);
421 /* write the record header */
422 nwritten = fwrite(&HeaderFrame, 1, sizeof(t_5VW_TimeStamped_Header), wdh->fh);
423 if (nwritten != sizeof(t_5VW_TimeStamped_Header)) {
424 if (nwritten == 0 && ferror(wdh->fh))
427 *err = WTAP_ERR_SHORT_WRITE;
432 nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
433 if (nwritten != phdr->caplen) {
434 if (nwritten == 0 && ferror(wdh->fh))
437 *err = WTAP_ERR_SHORT_WRITE;
441 wdh->dump._5views->nframes ++;
446 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
448 t_5VW_Capture_Header file_hdr;
451 if (fseek(wdh->fh, 0, SEEK_SET) == -1) {
456 /* fill in the Info_Header */
457 file_hdr.Info_Header.Signature = htolel(CST_5VW_INFO_HEADER_KEY);
458 file_hdr.Info_Header.Size = htolel(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
459 file_hdr.Info_Header.Version = htolel(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
460 file_hdr.Info_Header.DataSize = htolel(sizeof(t_5VW_Attributes_Header)
462 + sizeof(t_5VW_Attributes_Header)
464 /* Total size of data included in the Info Record (except the header size) */
465 file_hdr.Info_Header.FileType = htolel(wtap_encap[wdh->encap]); /* Type of the file */
466 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
467 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
468 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
470 /* fill in the HeaderDateCreation */
471 file_hdr.HeaderDateCreation.Type = htolel(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
472 file_hdr.HeaderDateCreation.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
473 file_hdr.HeaderDateCreation.Nb = htoles(1); /* Number of elements */
475 /* fill in the Time field */
479 file_hdr.Time = htolel(time(NULL));
481 /* fill in the Time field */
482 file_hdr.HeaderNbFrames.Type = htolel(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
483 file_hdr.HeaderNbFrames.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
484 file_hdr.HeaderNbFrames.Nb = htoles(1); /* Number of elements */
486 /* fill in the number of frames saved */
487 file_hdr.TramesStockeesInFile = htolel(wdh->dump._5views->nframes);
489 /* Write the file header. */
490 nwritten = fwrite(&file_hdr, 1, sizeof(t_5VW_Capture_Header), wdh->fh);
491 if (nwritten != sizeof(t_5VW_Capture_Header)) {
492 if (nwritten == 0 && ferror(wdh->fh))
495 *err = WTAP_ERR_SHORT_WRITE;