4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "file_wrappers.h"
33 guint32 Size; /* Total size of Header in bytes (included Signature) */
34 guint32 Version; /* Identify version and so the format of this record */
35 guint32 DataSize; /* Total size of data included in the Info Record (except the header size) */
36 guint32 FileType; /* Type of the file */
37 guint32 Reserved[3]; /* Reserved for future use */
42 guint32 Type; /* Id of the attribute */
43 guint16 Size; /* Size of the data part of the attribute (not including header size) */
44 guint16 Nb; /* Number of elements */
45 }t_5VW_Attributes_Header;
48 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAAU /* signature */
50 #define CST_5VW_INFO_RECORD_VERSION 0x00010000U /* version */
52 #define CST_5VW_DECALE_FILE_TYPE 24
53 #define CST_5VW_SECTION_CAPTURES 0x08U
54 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
55 #define CST_5VW_FLAT_FILE 0x10000000U
56 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
57 #define CST_5VW_FAMILY_CAP_ETH 0x01U
58 #define CST_5VW_FAMILY_CAP_WAN 0x02U
59 #define CST_5VW_DECALE_FILE_FAMILY 12
60 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
61 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
62 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
63 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
65 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000U
67 #define CST_5VW_FRAME_RECORD 0x00000000U
68 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEEU
72 t_5VW_Info_Header Info_Header;
73 t_5VW_Attributes_Header HeaderDateCreation;
75 t_5VW_Attributes_Header HeaderNbFrames;
76 guint32 TramesStockeesInFile;
77 }t_5VW_Capture_Header;
81 guint32 Key; /* 0x3333EEEE */
82 guint16 HeaderSize; /* Actual size of this header in bytes (32) */
83 guint16 HeaderType; /* Exact type of this header (0x4000) */
84 guint32 RecType; /* Type of record */
85 guint32 RecSubType; /* Subtype of record */
86 guint32 RecSize; /* Size of one record */
87 guint32 RecNb; /* Number of records */
90 guint32 RecInfo; /* Info about Alarm / Event / Frame captured */
91 }t_5VW_TimeStamped_Header;
94 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000U
95 #define CST_5VW_IA_DATE_CREATION 0x80000007U /* Struct t_Attrib_Date_Create */
96 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000U
97 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
98 #define CST_5VW_SYSTEM_RECORD 0x00000000U
100 static gboolean _5views_read(wtap *wth, int *err, gchar **err_info,
101 gint64 *data_offset);
102 static gboolean _5views_seek_read(wtap *wth, gint64 seek_off,
103 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
104 static int _5views_read_header(wtap *wth, FILE_T fh, t_5VW_TimeStamped_Header *hdr,
105 struct wtap_pkthdr *phdr, int *err, gchar **err_info);
107 static gboolean _5views_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const guint8 *pd, int *err, gchar **err_info);
108 static gboolean _5views_dump_finish(wtap_dumper *wdh, int *err);
112 _5views_open(wtap *wth, int *err, gchar **err_info)
114 t_5VW_Capture_Header Capture_Header;
115 int encap = WTAP_ENCAP_UNKNOWN;
117 if (!wtap_read_bytes(wth->fh, &Capture_Header.Info_Header,
118 sizeof(t_5VW_Info_Header), err, err_info)) {
119 if (*err != WTAP_ERR_SHORT_READ)
120 return WTAP_OPEN_ERROR;
121 return WTAP_OPEN_NOT_MINE;
124 /* Check whether that's 5Views format or not */
125 if(Capture_Header.Info_Header.Signature != CST_5VW_INFO_HEADER_KEY)
127 return WTAP_OPEN_NOT_MINE;
131 Capture_Header.Info_Header.Version =
132 pletoh32(&Capture_Header.Info_Header.Version);
133 switch (Capture_Header.Info_Header.Version) {
135 case CST_5VW_INFO_RECORD_VERSION:
139 *err = WTAP_ERR_UNSUPPORTED;
140 *err_info = g_strdup_printf("5views: header version %u unsupported", Capture_Header.Info_Header.Version);
141 return WTAP_OPEN_ERROR;
144 /* Check File Type */
145 Capture_Header.Info_Header.FileType =
146 pletoh32(&Capture_Header.Info_Header.FileType);
147 if((Capture_Header.Info_Header.FileType & CST_5VW_CAPTURE_FILE_TYPE_MASK) != CST_5VW_CAPTURE_FILEID)
149 *err = WTAP_ERR_UNSUPPORTED;
150 *err_info = g_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header.Info_Header.Version);
151 return WTAP_OPEN_ERROR;
154 /* Check possible Encap */
155 switch (Capture_Header.Info_Header.FileType) {
156 case CST_5VW_CAPTURE_ETH_FILEID:
157 encap = WTAP_ENCAP_ETHERNET;
159 /* case CST_5VW_CAPTURE_WAN_FILEID:
163 *err = WTAP_ERR_UNSUPPORTED;
164 *err_info = g_strdup_printf("5views: network type %u unknown or unsupported",
165 Capture_Header.Info_Header.FileType);
166 return WTAP_OPEN_ERROR;
169 /* read the remaining header information */
170 if (!wtap_read_bytes(wth->fh, &Capture_Header.HeaderDateCreation,
171 sizeof (t_5VW_Capture_Header) - sizeof(t_5VW_Info_Header), err, err_info))
172 return WTAP_OPEN_ERROR;
174 /* This is a 5views capture file */
175 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_5VIEWS;
176 wth->subtype_read = _5views_read;
177 wth->subtype_seek_read = _5views_seek_read;
178 wth->file_encap = encap;
179 wth->snapshot_length = 0; /* not available in header */
180 wth->file_tsprec = WTAP_TSPREC_NSEC;
182 return WTAP_OPEN_MINE;
185 /* Read the next packet */
187 _5views_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
189 t_5VW_TimeStamped_Header TimeStamped_Header;
192 * Keep reading until we see a record with a subtype of
193 * CST_5VW_FRAME_RECORD.
197 *data_offset = file_tell(wth->fh);
199 /* Read record header. */
200 if (!_5views_read_header(wth, wth->fh, &TimeStamped_Header,
201 &wth->phdr, err, err_info))
204 if (TimeStamped_Header.RecSubType == CST_5VW_FRAME_RECORD) {
206 * OK, this is a packet.
212 * Not a packet - skip to the next record.
214 if (file_seek(wth->fh, TimeStamped_Header.RecSize, SEEK_CUR, err) == -1)
218 if (wth->phdr.caplen > WTAP_MAX_PACKET_SIZE) {
220 * Probably a corrupt capture file; don't blow up trying
221 * to allocate space for an immensely-large packet.
223 *err = WTAP_ERR_BAD_FILE;
224 *err_info = g_strdup_printf("5views: File has %u-byte packet, bigger than maximum of %u",
225 wth->phdr.caplen, WTAP_MAX_PACKET_SIZE);
229 return wtap_read_packet_bytes(wth->fh, wth->frame_buffer,
230 wth->phdr.caplen, err, err_info);
234 _5views_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
235 Buffer *buf, int *err, gchar **err_info)
237 t_5VW_TimeStamped_Header TimeStamped_Header;
239 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
245 if (!_5views_read_header(wth, wth->random_fh, &TimeStamped_Header,
246 phdr, err, err_info)) {
248 *err = WTAP_ERR_SHORT_READ;
253 * Read the packet data.
255 return wtap_read_packet_bytes(wth->random_fh, buf, phdr->caplen,
259 /* Read the header of the next packet. Return TRUE on success, FALSE
262 _5views_read_header(wtap *wth, FILE_T fh, t_5VW_TimeStamped_Header *hdr,
263 struct wtap_pkthdr *phdr, int *err, gchar **err_info)
265 /* Read record header. */
266 if (!wtap_read_bytes_or_eof(fh, hdr, (unsigned int)sizeof(t_5VW_TimeStamped_Header),
270 hdr->Key = pletoh32(&hdr->Key);
271 if (hdr->Key != CST_5VW_RECORDS_HEADER_KEY) {
272 *err = WTAP_ERR_BAD_FILE;
273 *err_info = g_strdup_printf("5views: Time-stamped header has bad key value 0x%08X",
278 hdr->RecSubType = pletoh32(&hdr->RecSubType);
279 hdr->RecSize = pletoh32(&hdr->RecSize);
280 hdr->Utc = pletoh32(&hdr->Utc);
281 hdr->NanoSecondes = pletoh32(&hdr->NanoSecondes);
283 phdr->rec_type = REC_TYPE_PACKET;
284 phdr->presence_flags = WTAP_HAS_TS;
285 phdr->ts.secs = hdr->Utc;
286 phdr->ts.nsecs = hdr->NanoSecondes;
287 phdr->caplen = hdr->RecSize;
288 phdr->len = hdr->RecSize;
290 switch (wth->file_encap) {
292 case WTAP_ENCAP_ETHERNET:
293 /* We assume there's no FCS in this frame. */
294 phdr->pseudo_header.eth.fcs_len = 0;
305 static const int wtap_encap[] = {
306 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
307 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ethernet */
309 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
311 /* Returns 0 if we could write the specified encapsulation type,
312 an error indication otherwise. */
313 int _5views_dump_can_write_encap(int encap)
315 /* Per-packet encapsulations aren't supported. */
316 if (encap == WTAP_ENCAP_PER_PACKET)
317 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
319 if (encap < 0 || (unsigned int) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
320 return WTAP_ERR_UNWRITABLE_ENCAP;
325 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
327 gboolean _5views_dump_open(wtap_dumper *wdh, int *err)
329 _5views_dump_t *_5views;
331 /* We can't fill in all the fields in the file header, as we
332 haven't yet written any packets. As we'll have to rewrite
333 the header when we've written out all the packets, we just
334 skip over the header for now. */
335 if (wtap_dump_file_seek(wdh, sizeof(t_5VW_Capture_Header), SEEK_SET, err) == -1)
338 /* This is a 5Views file */
339 wdh->subtype_write = _5views_dump;
340 wdh->subtype_finish = _5views_dump_finish;
341 _5views = (_5views_dump_t *)g_malloc(sizeof(_5views_dump_t));
342 wdh->priv = (void *)_5views;
343 _5views->nframes = 0;
348 /* Write a record for a packet to a dump file.
349 Returns TRUE on success, FALSE on failure. */
350 static gboolean _5views_dump(wtap_dumper *wdh,
351 const struct wtap_pkthdr *phdr,
352 const guint8 *pd, int *err, gchar **err_info _U_)
354 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
355 t_5VW_TimeStamped_Header HeaderFrame;
357 /* We can only write packet records. */
358 if (phdr->rec_type != REC_TYPE_PACKET) {
359 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
363 /* Don't write out something bigger than we can read. */
364 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
365 *err = WTAP_ERR_PACKET_TOO_LARGE;
370 /* constant fields */
371 HeaderFrame.Key = GUINT32_TO_LE(CST_5VW_RECORDS_HEADER_KEY);
372 HeaderFrame.HeaderSize = GUINT16_TO_LE(sizeof(t_5VW_TimeStamped_Header));
373 HeaderFrame.HeaderType = GUINT16_TO_LE(CST_5VW_TIMESTAMPED_HEADER_TYPE);
374 HeaderFrame.RecType = GUINT32_TO_LE(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
375 HeaderFrame.RecSubType = GUINT32_TO_LE(CST_5VW_FRAME_RECORD);
376 HeaderFrame.RecNb = GUINT32_TO_LE(1);
378 /* record-dependent fields */
379 HeaderFrame.Utc = GUINT32_TO_LE(phdr->ts.secs);
380 HeaderFrame.NanoSecondes = GUINT32_TO_LE(phdr->ts.nsecs);
381 HeaderFrame.RecSize = GUINT32_TO_LE(phdr->len);
382 HeaderFrame.RecInfo = GUINT32_TO_LE(0);
384 /* write the record header */
385 if (!wtap_dump_file_write(wdh, &HeaderFrame,
386 sizeof(t_5VW_TimeStamped_Header), err))
390 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
398 static gboolean _5views_dump_finish(wtap_dumper *wdh, int *err)
400 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
401 t_5VW_Capture_Header file_hdr;
403 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
406 /* fill in the Info_Header */
407 file_hdr.Info_Header.Signature = GUINT32_TO_LE(CST_5VW_INFO_HEADER_KEY);
408 file_hdr.Info_Header.Size = GUINT32_TO_LE(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
409 file_hdr.Info_Header.Version = GUINT32_TO_LE(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
410 file_hdr.Info_Header.DataSize = GUINT32_TO_LE(sizeof(t_5VW_Attributes_Header)
412 + sizeof(t_5VW_Attributes_Header)
414 /* Total size of data included in the Info Record (except the header size) */
415 file_hdr.Info_Header.FileType = GUINT32_TO_LE(wtap_encap[wdh->encap]); /* Type of the file */
416 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
417 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
418 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
420 /* fill in the HeaderDateCreation */
421 file_hdr.HeaderDateCreation.Type = GUINT32_TO_LE(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
422 file_hdr.HeaderDateCreation.Size = GUINT16_TO_LE(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
423 file_hdr.HeaderDateCreation.Nb = GUINT16_TO_LE(1); /* Number of elements */
425 /* fill in the Time field */
429 file_hdr.Time = GUINT32_TO_LE(time(NULL));
431 /* fill in the Time field */
432 file_hdr.HeaderNbFrames.Type = GUINT32_TO_LE(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
433 file_hdr.HeaderNbFrames.Size = GUINT16_TO_LE(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
434 file_hdr.HeaderNbFrames.Nb = GUINT16_TO_LE(1); /* Number of elements */
436 /* fill in the number of frames saved */
437 file_hdr.TramesStockeesInFile = GUINT32_TO_LE(_5views->nframes);
439 /* Write the file header. */
440 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof(t_5VW_Capture_Header),
448 * Editor modelines - http://www.wireshark.org/tools/modelines.html
453 * indent-tabs-mode: t
456 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
457 * :indentSize=8:tabSize=8:noTabs=false: