add WERR_INVALID_STATE
[wireshark-wip.git] / wiretap / 5views.c
blob10a5ecc86cedcfcf75fce0b1160700dd03bccd75
1 /* 5views.c
3 * $Id$
5 * Wiretap Library
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "config.h"
24 #include <errno.h>
25 #include <string.h>
26 #include <time.h>
28 #include "wtap-int.h"
29 #include "file_wrappers.h"
30 #include "buffer.h"
31 #include "5views.h"
34 typedef struct
36 guint32 Signature;
37 guint32 Size; /* Total size of Header in bytes (included Signature) */
38 guint32 Version; /* Identify version and so the format of this record */
39 guint32 DataSize; /* Total size of data included in the Info Record (except the header size) */
40 guint32 FileType; /* Type of the file */
41 guint32 Reserved[3]; /* Reserved for future use */
42 }t_5VW_Info_Header;
44 typedef struct
46 guint32 Type; /* Id of the attribute */
47 guint16 Size; /* Size of the data part of the attribute (not including header size) */
48 guint16 Nb; /* Number of elements */
49 }t_5VW_Attributes_Header;
52 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAAU /* signature */
54 #define CST_5VW_INFO_RECORD_VERSION 0x00010000U /* version */
56 #define CST_5VW_DECALE_FILE_TYPE 24
57 #define CST_5VW_SECTION_CAPTURES 0x08U
58 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
59 #define CST_5VW_FLAT_FILE 0x10000000U
60 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
61 #define CST_5VW_FAMILY_CAP_ETH 0x01U
62 #define CST_5VW_FAMILY_CAP_WAN 0x02U
63 #define CST_5VW_DECALE_FILE_FAMILY 12
64 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
65 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
66 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
67 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
69 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000U
71 #define CST_5VW_FRAME_RECORD 0x00000000U
72 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEEU
74 typedef struct
76 t_5VW_Info_Header Info_Header;
77 t_5VW_Attributes_Header HeaderDateCreation;
78 guint32 Time;
79 t_5VW_Attributes_Header HeaderNbFrames;
80 guint32 TramesStockeesInFile;
81 }t_5VW_Capture_Header;
83 typedef struct
85 guint32 Key; /* 0x3333EEEE */
86 guint16 HeaderSize; /* Actual size of this header in bytes (32) */
87 guint16 HeaderType; /* Exact type of this header (0x4000) */
88 guint32 RecType; /* Type of record */
89 guint32 RecSubType; /* Subtype of record */
90 guint32 RecSize; /* Size of one record */
91 guint32 RecNb; /* Number of records */
92 guint32 Utc;
93 guint32 NanoSecondes;
94 guint32 RecInfo; /* Info about Alarm / Event / Frame captured */
95 }t_5VW_TimeStamped_Header;
98 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000U
99 #define CST_5VW_IA_DATE_CREATION 0x80000007U /* Struct t_Attrib_Date_Create */
100 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000U
101 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
102 #define CST_5VW_SYSTEM_RECORD 0x00000000U
104 static gboolean _5views_read(wtap *wth, int *err, gchar **err_info,
105 gint64 *data_offset);
106 static gboolean _5views_seek_read(wtap *wth, gint64 seek_off,
107 struct wtap_pkthdr *phdr, Buffer *buf, int length,
108 int *err, gchar **err_info);
109 static int _5views_read_header(wtap *wth, FILE_T fh, t_5VW_TimeStamped_Header *hdr,
110 struct wtap_pkthdr *phdr, int *err, gchar **err_info);
112 static gboolean _5views_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, const guint8 *pd, int *err);
113 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err);
116 int _5views_open(wtap *wth, int *err, gchar **err_info)
118 int bytes_read;
119 t_5VW_Capture_Header Capture_Header;
120 int encap = WTAP_ENCAP_UNKNOWN;
122 errno = WTAP_ERR_CANT_READ;
123 bytes_read = file_read(&Capture_Header.Info_Header, sizeof(t_5VW_Info_Header), wth->fh);
124 if (bytes_read != sizeof(t_5VW_Info_Header)) {
125 *err = file_error(wth->fh, err_info);
126 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
127 return -1;
128 return 0;
131 /* Check whether that's 5Views format or not */
132 if(Capture_Header.Info_Header.Signature != CST_5VW_INFO_HEADER_KEY)
134 return 0;
137 /* Check Version */
138 Capture_Header.Info_Header.Version =
139 pletohl(&Capture_Header.Info_Header.Version);
140 switch (Capture_Header.Info_Header.Version) {
142 case CST_5VW_INFO_RECORD_VERSION:
143 break;
145 default:
146 *err = WTAP_ERR_UNSUPPORTED;
147 *err_info = g_strdup_printf("5views: header version %u unsupported", Capture_Header.Info_Header.Version);
148 return -1;
151 /* Check File Type */
152 Capture_Header.Info_Header.FileType =
153 pletohl(&Capture_Header.Info_Header.FileType);
154 if((Capture_Header.Info_Header.FileType & CST_5VW_CAPTURE_FILE_TYPE_MASK) != CST_5VW_CAPTURE_FILEID)
156 *err = WTAP_ERR_UNSUPPORTED;
157 *err_info = g_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header.Info_Header.Version);
158 return -1;
161 /* Check possible Encap */
162 switch (Capture_Header.Info_Header.FileType) {
163 case CST_5VW_CAPTURE_ETH_FILEID:
164 encap = WTAP_ENCAP_ETHERNET;
165 break;
166 /* case CST_5VW_CAPTURE_WAN_FILEID:
167 break;
169 default:
170 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
171 *err_info = g_strdup_printf("5views: network type %u unknown or unsupported",
172 Capture_Header.Info_Header.FileType);
173 return -1;
176 /* read the remaining header information */
177 bytes_read = file_read(&Capture_Header.HeaderDateCreation, sizeof (t_5VW_Capture_Header) - sizeof(t_5VW_Info_Header), wth->fh);
178 if (bytes_read != sizeof (t_5VW_Capture_Header)- sizeof(t_5VW_Info_Header) ) {
179 *err = file_error(wth->fh, err_info);
180 if (*err == 0)
181 *err = WTAP_ERR_SHORT_READ;
182 return -1;
185 /* This is a 5views capture file */
186 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_5VIEWS;
187 wth->subtype_read = _5views_read;
188 wth->subtype_seek_read = _5views_seek_read;
189 wth->file_encap = encap;
190 wth->snapshot_length = 0; /* not available in header */
191 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
193 return 1;
196 /* Read the next packet */
197 static gboolean
198 _5views_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
200 t_5VW_TimeStamped_Header TimeStamped_Header;
203 * Keep reading until we see a record with a subtype of
204 * CST_5VW_FRAME_RECORD.
208 *data_offset = file_tell(wth->fh);
210 /* Read record header. */
211 if (!_5views_read_header(wth, wth->fh, &TimeStamped_Header,
212 &wth->phdr, err, err_info))
213 return FALSE;
215 if (TimeStamped_Header.RecSubType == CST_5VW_FRAME_RECORD) {
217 * OK, this is a packet.
219 break;
223 * Not a packet - skip to the next record.
225 if (file_seek(wth->fh, TimeStamped_Header.RecSize, SEEK_CUR, err) == -1)
226 return FALSE;
227 } while (1);
229 if (wth->phdr.caplen > WTAP_MAX_PACKET_SIZE) {
231 * Probably a corrupt capture file; don't blow up trying
232 * to allocate space for an immensely-large packet.
234 *err = WTAP_ERR_BAD_FILE;
235 *err_info = g_strdup_printf("5views: File has %u-byte packet, bigger than maximum of %u",
236 wth->phdr.caplen, WTAP_MAX_PACKET_SIZE);
237 return FALSE;
240 return wtap_read_packet_bytes(wth->fh, wth->frame_buffer,
241 wth->phdr.caplen, err, err_info);
244 static gboolean
245 _5views_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
246 Buffer *buf, int length, int *err, gchar **err_info)
248 t_5VW_TimeStamped_Header TimeStamped_Header;
250 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
251 return FALSE;
254 * Read the header.
256 if (!_5views_read_header(wth, wth->random_fh, &TimeStamped_Header,
257 phdr, err, err_info))
258 return FALSE;
261 * Read the packet data.
263 return wtap_read_packet_bytes(wth->random_fh, buf, length,
264 err, err_info);
267 /* Read the header of the next packet. Return TRUE on success, FALSE
268 on error. */
269 static gboolean
270 _5views_read_header(wtap *wth, FILE_T fh, t_5VW_TimeStamped_Header *hdr,
271 struct wtap_pkthdr *phdr, int *err, gchar **err_info)
273 int bytes_read, bytes_to_read;
275 bytes_to_read = sizeof(t_5VW_TimeStamped_Header);
277 /* Read record header. */
278 bytes_read = file_read(hdr, bytes_to_read, fh);
279 if (bytes_read != bytes_to_read) {
280 *err = file_error(fh, err_info);
281 if (*err == 0 && bytes_read != 0) {
282 *err = WTAP_ERR_SHORT_READ;
284 return FALSE;
287 hdr->Key = pletohl(&hdr->Key);
288 if (hdr->Key != CST_5VW_RECORDS_HEADER_KEY) {
289 *err = WTAP_ERR_BAD_FILE;
290 *err_info = g_strdup_printf("5views: Time-stamped header has bad key value 0x%08X",
291 hdr->Key);
292 return FALSE;
295 hdr->RecSubType = pletohl(&hdr->RecSubType);
296 hdr->RecSize = pletohl(&hdr->RecSize);
297 hdr->Utc = pletohl(&hdr->Utc);
298 hdr->NanoSecondes = pletohl(&hdr->NanoSecondes);
300 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
301 phdr->ts.secs = hdr->Utc;
302 phdr->ts.nsecs = hdr->NanoSecondes;
303 phdr->caplen = hdr->RecSize;
304 phdr->len = hdr->RecSize;
306 switch (wth->file_encap) {
308 case WTAP_ENCAP_ETHERNET:
309 /* We assume there's no FCS in this frame. */
310 phdr->pseudo_header.eth.fcs_len = 0;
311 break;
314 return TRUE;
317 typedef struct {
318 guint32 nframes;
319 } _5views_dump_t;
321 static const int wtap_encap[] = {
322 -1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
323 CST_5VW_CAPTURE_ETH_FILEID, /* WTAP_ENCAP_ETHERNET -> Ethernet */
325 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
327 /* Returns 0 if we could write the specified encapsulation type,
328 an error indication otherwise. */
329 int _5views_dump_can_write_encap(int encap)
331 /* Per-packet encapsulations aren't supported. */
332 if (encap == WTAP_ENCAP_PER_PACKET)
333 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
335 if (encap < 0 || (unsigned) encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
336 return WTAP_ERR_UNSUPPORTED_ENCAP;
338 return 0;
341 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
342 failure */
343 gboolean _5views_dump_open(wtap_dumper *wdh, int *err)
345 _5views_dump_t *_5views;
347 /* We can't fill in all the fields in the file header, as we
348 haven't yet written any packets. As we'll have to rewrite
349 the header when we've written out all the packets, we just
350 skip over the header for now. */
351 if (wtap_dump_file_seek(wdh, sizeof(t_5VW_Capture_Header), SEEK_SET, err) == -1)
352 return FALSE;
354 /* This is a 5Views file */
355 wdh->subtype_write = _5views_dump;
356 wdh->subtype_close = _5views_dump_close;
357 _5views = (_5views_dump_t *)g_malloc(sizeof(_5views_dump_t));
358 wdh->priv = (void *)_5views;
359 _5views->nframes = 0;
361 return TRUE;
364 /* Write a record for a packet to a dump file.
365 Returns TRUE on success, FALSE on failure. */
366 static gboolean _5views_dump(wtap_dumper *wdh,
367 const struct wtap_pkthdr *phdr,
368 const guint8 *pd, int *err)
370 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
371 t_5VW_TimeStamped_Header HeaderFrame;
373 /* Frame Header */
374 /* constant fields */
375 HeaderFrame.Key = htolel(CST_5VW_RECORDS_HEADER_KEY);
376 HeaderFrame.HeaderSize = htoles(sizeof(t_5VW_TimeStamped_Header));
377 HeaderFrame.HeaderType = htoles(CST_5VW_TIMESTAMPED_HEADER_TYPE);
378 HeaderFrame.RecType = htolel(CST_5VW_CAPTURES_RECORD | CST_5VW_SYSTEM_RECORD);
379 HeaderFrame.RecSubType = htolel(CST_5VW_FRAME_RECORD);
380 HeaderFrame.RecNb = htolel(1);
382 /* record-dependent fields */
383 HeaderFrame.Utc = htolel(phdr->ts.secs);
384 HeaderFrame.NanoSecondes = htolel(phdr->ts.nsecs);
385 HeaderFrame.RecSize = htolel(phdr->len);
386 HeaderFrame.RecInfo = htolel(0);
388 /* write the record header */
389 if (!wtap_dump_file_write(wdh, &HeaderFrame,
390 sizeof(t_5VW_TimeStamped_Header), err))
391 return FALSE;
393 /* write the data */
394 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
395 return FALSE;
397 _5views->nframes ++;
399 return TRUE;
402 static gboolean _5views_dump_close(wtap_dumper *wdh, int *err)
404 _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv;
405 t_5VW_Capture_Header file_hdr;
407 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
408 return FALSE;
410 /* fill in the Info_Header */
411 file_hdr.Info_Header.Signature = htolel(CST_5VW_INFO_HEADER_KEY);
412 file_hdr.Info_Header.Size = htolel(sizeof(t_5VW_Info_Header)); /* Total size of Header in bytes (included Signature) */
413 file_hdr.Info_Header.Version = htolel(CST_5VW_INFO_RECORD_VERSION); /* Identify version and so the format of this record */
414 file_hdr.Info_Header.DataSize = htolel(sizeof(t_5VW_Attributes_Header)
415 + sizeof(guint32)
416 + sizeof(t_5VW_Attributes_Header)
417 + sizeof(guint32));
418 /* Total size of data included in the Info Record (except the header size) */
419 file_hdr.Info_Header.FileType = htolel(wtap_encap[wdh->encap]); /* Type of the file */
420 file_hdr.Info_Header.Reserved[0] = 0; /* Reserved for future use */
421 file_hdr.Info_Header.Reserved[1] = 0; /* Reserved for future use */
422 file_hdr.Info_Header.Reserved[2] = 0; /* Reserved for future use */
424 /* fill in the HeaderDateCreation */
425 file_hdr.HeaderDateCreation.Type = htolel(CST_5VW_IA_DATE_CREATION); /* Id of the attribute */
426 file_hdr.HeaderDateCreation.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
427 file_hdr.HeaderDateCreation.Nb = htoles(1); /* Number of elements */
429 /* fill in the Time field */
430 #ifdef _WIN32
431 _tzset();
432 #endif
433 file_hdr.Time = htolel(time(NULL));
435 /* fill in the Time field */
436 file_hdr.HeaderNbFrames.Type = htolel(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES); /* Id of the attribute */
437 file_hdr.HeaderNbFrames.Size = htoles(sizeof(guint32)); /* Size of the data part of the attribute (not including header size) */
438 file_hdr.HeaderNbFrames.Nb = htoles(1); /* Number of elements */
440 /* fill in the number of frames saved */
441 file_hdr.TramesStockeesInFile = htolel(_5views->nframes);
443 /* Write the file header. */
444 if (!wtap_dump_file_write(wdh, &file_hdr, sizeof(t_5VW_Capture_Header),
445 err))
446 return FALSE;
448 return TRUE;