4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "file_wrappers.h"
20 uint32_t Size
; /* Total size of Header in bytes (included Signature) */
21 uint32_t Version
; /* Identify version and so the format of this record */
22 uint32_t DataSize
; /* Total size of data included in the Info Record (except the header size) */
23 uint32_t FileType
; /* Type of the file */
24 uint32_t Reserved
[3]; /* Reserved for future use */
29 uint32_t Type
; /* Id of the attribute */
30 uint16_t Size
; /* Size of the data part of the attribute (not including header size) */
31 uint16_t Nb
; /* Number of elements */
32 }t_5VW_Attributes_Header
;
35 #define CST_5VW_INFO_HEADER_KEY 0xAAAAAAAAU /* signature */
37 #define CST_5VW_INFO_RECORD_VERSION 0x00010000U /* version */
39 #define CST_5VW_DECALE_FILE_TYPE 24
40 #define CST_5VW_SECTION_CAPTURES 0x08U
41 #define CST_5VW_CAPTURES_FILE (CST_5VW_SECTION_CAPTURES << CST_5VW_DECALE_FILE_TYPE) /* 0x08000000 */
42 #define CST_5VW_FLAT_FILE 0x10000000U
43 #define CST_5VW_CAPTURE_FILEID (CST_5VW_FLAT_FILE | CST_5VW_CAPTURES_FILE)
44 #define CST_5VW_FAMILY_CAP_ETH 0x01U
45 #define CST_5VW_FAMILY_CAP_WAN 0x02U
46 #define CST_5VW_DECALE_FILE_FAMILY 12
47 #define CST_5VW_CAP_ETH (CST_5VW_FAMILY_CAP_ETH << CST_5VW_DECALE_FILE_FAMILY) /* 0x00001000 */
48 #define CST_5VW_CAP_WAN (CST_5VW_FAMILY_CAP_WAN << CST_5VW_DECALE_FILE_FAMILY) /* 0x00002000 */
49 #define CST_5VW_CAPTURE_ETH_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_ETH)
50 #define CST_5VW_CAPTURE_WAN_FILEID (CST_5VW_CAPTURE_FILEID | CST_5VW_CAP_WAN)
52 #define CST_5VW_CAPTURE_FILE_TYPE_MASK 0xFF000000U
54 #define CST_5VW_FRAME_RECORD 0x00000000U
55 #define CST_5VW_RECORDS_HEADER_KEY 0x3333EEEEU
59 t_5VW_Info_Header Info_Header
;
60 t_5VW_Attributes_Header HeaderDateCreation
;
62 t_5VW_Attributes_Header HeaderNbFrames
;
63 uint32_t TramesStockeesInFile
;
64 }t_5VW_Capture_Header
;
68 uint32_t Key
; /* 0x3333EEEE */
69 uint16_t HeaderSize
; /* Actual size of this header in bytes (32) */
70 uint16_t HeaderType
; /* Exact type of this header (0x4000) */
71 uint32_t RecType
; /* Type of record */
72 uint32_t RecSubType
; /* Subtype of record */
73 uint32_t RecSize
; /* Size of one record */
74 uint32_t RecNb
; /* Number of records */
76 uint32_t NanoSecondes
;
77 uint32_t RecInfo
; /* Info about Alarm / Event / Frame captured */
78 }t_5VW_TimeStamped_Header
;
81 #define CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES 0x20000000U
82 #define CST_5VW_IA_DATE_CREATION 0x80000007U /* Struct t_Attrib_Date_Create */
83 #define CST_5VW_TIMESTAMPED_HEADER_TYPE 0x4000U
84 #define CST_5VW_CAPTURES_RECORD (CST_5VW_SECTION_CAPTURES << 28) /* 0x80000000 */
85 #define CST_5VW_SYSTEM_RECORD 0x00000000U
87 static bool _5views_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
,
88 char **err_info
, int64_t *data_offset
);
89 static bool _5views_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
,
90 Buffer
*buf
, int *err
, char **err_info
);
91 static bool _5views_read_header(wtap
*wth
, FILE_T fh
, t_5VW_TimeStamped_Header
*hdr
,
92 wtap_rec
*rec
, int *err
, char **err_info
);
94 static bool _5views_dump(wtap_dumper
*wdh
, const wtap_rec
*rec
, const uint8_t *pd
, int *err
, char **err_info
);
95 static bool _5views_dump_finish(wtap_dumper
*wdh
, int *err
, char **err_info
);
97 static int _5views_file_type_subtype
= -1;
99 void register_5views(void);
102 _5views_open(wtap
*wth
, int *err
, char **err_info
)
104 t_5VW_Capture_Header Capture_Header
;
105 int encap
= WTAP_ENCAP_UNKNOWN
;
107 if (!wtap_read_bytes(wth
->fh
, &Capture_Header
.Info_Header
,
108 sizeof(t_5VW_Info_Header
), err
, err_info
)) {
109 if (*err
!= WTAP_ERR_SHORT_READ
)
110 return WTAP_OPEN_ERROR
;
111 return WTAP_OPEN_NOT_MINE
;
114 /* Check whether that's 5Views format or not */
115 if(Capture_Header
.Info_Header
.Signature
!= CST_5VW_INFO_HEADER_KEY
)
117 return WTAP_OPEN_NOT_MINE
;
121 Capture_Header
.Info_Header
.Version
=
122 pletoh32(&Capture_Header
.Info_Header
.Version
);
123 switch (Capture_Header
.Info_Header
.Version
) {
125 case CST_5VW_INFO_RECORD_VERSION
:
129 *err
= WTAP_ERR_UNSUPPORTED
;
130 *err_info
= ws_strdup_printf("5views: header version %u unsupported", Capture_Header
.Info_Header
.Version
);
131 return WTAP_OPEN_ERROR
;
134 /* Check File Type */
135 Capture_Header
.Info_Header
.FileType
=
136 pletoh32(&Capture_Header
.Info_Header
.FileType
);
137 if((Capture_Header
.Info_Header
.FileType
& CST_5VW_CAPTURE_FILE_TYPE_MASK
) != CST_5VW_CAPTURE_FILEID
)
139 *err
= WTAP_ERR_UNSUPPORTED
;
140 *err_info
= ws_strdup_printf("5views: file is not a capture file (filetype is %u)", Capture_Header
.Info_Header
.Version
);
141 return WTAP_OPEN_ERROR
;
144 /* Check possible Encap */
145 switch (Capture_Header
.Info_Header
.FileType
) {
146 case CST_5VW_CAPTURE_ETH_FILEID
:
147 encap
= WTAP_ENCAP_ETHERNET
;
149 /* case CST_5VW_CAPTURE_WAN_FILEID:
153 *err
= WTAP_ERR_UNSUPPORTED
;
154 *err_info
= ws_strdup_printf("5views: network type %u unknown or unsupported",
155 Capture_Header
.Info_Header
.FileType
);
156 return WTAP_OPEN_ERROR
;
159 /* read the remaining header information */
160 if (!wtap_read_bytes(wth
->fh
, &Capture_Header
.HeaderDateCreation
,
161 sizeof (t_5VW_Capture_Header
) - sizeof(t_5VW_Info_Header
), err
, err_info
))
162 return WTAP_OPEN_ERROR
;
164 /* This is a 5views capture file */
165 wth
->file_type_subtype
= _5views_file_type_subtype
;
166 wth
->subtype_read
= _5views_read
;
167 wth
->subtype_seek_read
= _5views_seek_read
;
168 wth
->file_encap
= encap
;
169 wth
->snapshot_length
= 0; /* not available in header */
170 wth
->file_tsprec
= WTAP_TSPREC_NSEC
;
173 * Add an IDB; we don't know how many interfaces were
174 * involved, so we just say one interface, about which
175 * we only know the link-layer type, snapshot length,
176 * and time stamp resolution.
178 wtap_add_generated_idb(wth
);
180 return WTAP_OPEN_MINE
;
183 /* Read the next packet */
185 _5views_read(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
, int *err
,
186 char **err_info
, int64_t *data_offset
)
188 t_5VW_TimeStamped_Header TimeStamped_Header
;
191 * Keep reading until we see a record with a subtype of
192 * CST_5VW_FRAME_RECORD.
196 *data_offset
= file_tell(wth
->fh
);
198 /* Read record header. */
199 if (!_5views_read_header(wth
, wth
->fh
, &TimeStamped_Header
,
203 if (TimeStamped_Header
.RecSubType
== CST_5VW_FRAME_RECORD
) {
205 * OK, this is a packet.
211 * Not a packet - skip to the next record.
213 if (!wtap_read_bytes(wth
->fh
, NULL
, TimeStamped_Header
.RecSize
, err
, err_info
))
217 if (rec
->rec_header
.packet_header
.caplen
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
219 * Probably a corrupt capture file; don't blow up trying
220 * to allocate space for an immensely-large packet.
222 *err
= WTAP_ERR_BAD_FILE
;
223 *err_info
= ws_strdup_printf("5views: File has %u-byte packet, bigger than maximum of %u",
224 rec
->rec_header
.packet_header
.caplen
, WTAP_MAX_PACKET_SIZE_STANDARD
);
228 return wtap_read_packet_bytes(wth
->fh
, buf
,
229 rec
->rec_header
.packet_header
.caplen
, err
, err_info
);
233 _5views_seek_read(wtap
*wth
, int64_t seek_off
, wtap_rec
*rec
,
234 Buffer
*buf
, int *err
, char **err_info
)
236 t_5VW_TimeStamped_Header TimeStamped_Header
;
238 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
244 if (!_5views_read_header(wth
, wth
->random_fh
, &TimeStamped_Header
,
245 rec
, err
, err_info
)) {
247 *err
= WTAP_ERR_SHORT_READ
;
252 * Read the packet data.
254 return wtap_read_packet_bytes(wth
->random_fh
, buf
, rec
->rec_header
.packet_header
.caplen
,
258 /* Read the header of the next packet. Return true on success, false
261 _5views_read_header(wtap
*wth
, FILE_T fh
, t_5VW_TimeStamped_Header
*hdr
,
262 wtap_rec
*rec
, int *err
, char **err_info
)
264 /* Read record header. */
265 if (!wtap_read_bytes_or_eof(fh
, hdr
, (unsigned int)sizeof(t_5VW_TimeStamped_Header
),
269 hdr
->Key
= pletoh32(&hdr
->Key
);
270 if (hdr
->Key
!= CST_5VW_RECORDS_HEADER_KEY
) {
271 *err
= WTAP_ERR_BAD_FILE
;
272 *err_info
= ws_strdup_printf("5views: Time-stamped header has bad key value 0x%08X",
277 hdr
->RecSubType
= pletoh32(&hdr
->RecSubType
);
278 hdr
->RecSize
= pletoh32(&hdr
->RecSize
);
279 hdr
->Utc
= pletoh32(&hdr
->Utc
);
280 hdr
->NanoSecondes
= pletoh32(&hdr
->NanoSecondes
);
282 rec
->rec_type
= REC_TYPE_PACKET
;
283 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
284 rec
->presence_flags
= WTAP_HAS_TS
;
285 rec
->ts
.secs
= hdr
->Utc
;
286 rec
->ts
.nsecs
= hdr
->NanoSecondes
;
287 rec
->rec_header
.packet_header
.caplen
= hdr
->RecSize
;
288 rec
->rec_header
.packet_header
.len
= hdr
->RecSize
;
290 switch (wth
->file_encap
) {
292 case WTAP_ENCAP_ETHERNET
:
293 /* We assume there's no FCS in this frame. */
294 rec
->rec_header
.packet_header
.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 array_length(wtap_encap)
311 /* Returns 0 if we could write the specified encapsulation type,
312 an error indication otherwise. */
313 static 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 static bool _5views_dump_open(wtap_dumper
*wdh
, int *err
, char **err_info _U_
)
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
= g_new(_5views_dump_t
, 1);
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 bool _5views_dump(wtap_dumper
*wdh
,
352 const uint8_t *pd
, int *err
, char **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 (rec
->rec_type
!= REC_TYPE_PACKET
) {
359 *err
= WTAP_ERR_UNWRITABLE_REC_TYPE
;
364 * Make sure this packet doesn't have a link-layer type that
365 * differs from the one for the file.
367 if (wdh
->file_encap
!= rec
->rec_header
.packet_header
.pkt_encap
) {
368 *err
= WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED
;
372 /* Don't write out something bigger than we can read. */
373 if (rec
->rec_header
.packet_header
.caplen
> WTAP_MAX_PACKET_SIZE_STANDARD
) {
374 *err
= WTAP_ERR_PACKET_TOO_LARGE
;
379 /* constant fields */
380 HeaderFrame
.Key
= GUINT32_TO_LE(CST_5VW_RECORDS_HEADER_KEY
);
381 HeaderFrame
.HeaderSize
= GUINT16_TO_LE(sizeof(t_5VW_TimeStamped_Header
));
382 HeaderFrame
.HeaderType
= GUINT16_TO_LE(CST_5VW_TIMESTAMPED_HEADER_TYPE
);
383 HeaderFrame
.RecType
= GUINT32_TO_LE(CST_5VW_CAPTURES_RECORD
| CST_5VW_SYSTEM_RECORD
);
384 HeaderFrame
.RecSubType
= GUINT32_TO_LE(CST_5VW_FRAME_RECORD
);
385 HeaderFrame
.RecNb
= GUINT32_TO_LE(1);
387 /* record-dependent fields */
389 * XXX - is the frame time signed, or unsigned? If it's signed,
390 * we should check against INT32_MIN and INT32_MAX and make
393 if (rec
->ts
.secs
< 0 || rec
->ts
.secs
> WTAP_NSTIME_32BIT_SECS_MAX
) {
394 *err
= WTAP_ERR_TIME_STAMP_NOT_SUPPORTED
;
397 HeaderFrame
.Utc
= GUINT32_TO_LE((uint32_t)rec
->ts
.secs
);
398 HeaderFrame
.NanoSecondes
= GUINT32_TO_LE(rec
->ts
.nsecs
);
399 HeaderFrame
.RecSize
= GUINT32_TO_LE(rec
->rec_header
.packet_header
.len
);
400 HeaderFrame
.RecInfo
= GUINT32_TO_LE(0);
402 /* write the record header */
403 if (!wtap_dump_file_write(wdh
, &HeaderFrame
,
404 sizeof(t_5VW_TimeStamped_Header
), err
))
408 if (!wtap_dump_file_write(wdh
, pd
, rec
->rec_header
.packet_header
.caplen
, err
))
416 static bool _5views_dump_finish(wtap_dumper
*wdh
, int *err
, char **err_info _U_
)
418 _5views_dump_t
*_5views
= (_5views_dump_t
*)wdh
->priv
;
419 t_5VW_Capture_Header file_hdr
;
421 if (wtap_dump_file_seek(wdh
, 0, SEEK_SET
, err
) == -1)
424 /* fill in the Info_Header */
425 file_hdr
.Info_Header
.Signature
= GUINT32_TO_LE(CST_5VW_INFO_HEADER_KEY
);
426 file_hdr
.Info_Header
.Size
= GUINT32_TO_LE(sizeof(t_5VW_Info_Header
)); /* Total size of Header in bytes (included Signature) */
427 file_hdr
.Info_Header
.Version
= GUINT32_TO_LE(CST_5VW_INFO_RECORD_VERSION
); /* Identify version and so the format of this record */
428 file_hdr
.Info_Header
.DataSize
= GUINT32_TO_LE(sizeof(t_5VW_Attributes_Header
)
430 + sizeof(t_5VW_Attributes_Header
)
432 /* Total size of data included in the Info Record (except the header size) */
433 file_hdr
.Info_Header
.FileType
= GUINT32_TO_LE(wtap_encap
[wdh
->file_encap
]); /* Type of the file */
434 file_hdr
.Info_Header
.Reserved
[0] = 0; /* Reserved for future use */
435 file_hdr
.Info_Header
.Reserved
[1] = 0; /* Reserved for future use */
436 file_hdr
.Info_Header
.Reserved
[2] = 0; /* Reserved for future use */
438 /* fill in the HeaderDateCreation */
439 file_hdr
.HeaderDateCreation
.Type
= GUINT32_TO_LE(CST_5VW_IA_DATE_CREATION
); /* Id of the attribute */
440 file_hdr
.HeaderDateCreation
.Size
= GUINT16_TO_LE(sizeof(uint32_t)); /* Size of the data part of the attribute (not including header size) */
441 file_hdr
.HeaderDateCreation
.Nb
= GUINT16_TO_LE(1); /* Number of elements */
443 /* fill in the Time field */
447 file_hdr
.Time
= GUINT32_TO_LE(time(NULL
));
449 /* fill in the Time field */
450 file_hdr
.HeaderNbFrames
.Type
= GUINT32_TO_LE(CST_5VW_IA_CAP_INF_NB_TRAMES_STOCKEES
); /* Id of the attribute */
451 file_hdr
.HeaderNbFrames
.Size
= GUINT16_TO_LE(sizeof(uint32_t)); /* Size of the data part of the attribute (not including header size) */
452 file_hdr
.HeaderNbFrames
.Nb
= GUINT16_TO_LE(1); /* Number of elements */
454 /* fill in the number of frames saved */
455 file_hdr
.TramesStockeesInFile
= GUINT32_TO_LE(_5views
->nframes
);
457 /* Write the file header. */
458 if (!wtap_dump_file_write(wdh
, &file_hdr
, sizeof(t_5VW_Capture_Header
),
465 static const struct supported_block_type _5views_blocks_supported
[] = {
467 * We support packet blocks, with no comments or other options.
469 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
472 static const struct file_type_subtype_info _5views_info
= {
473 "InfoVista 5View capture", "5views", "5vw", NULL
,
474 true, BLOCKS_SUPPORTED(_5views_blocks_supported
),
475 _5views_dump_can_write_encap
, _5views_dump_open
, NULL
478 void register_5views(void)
480 _5views_file_type_subtype
= wtap_register_file_type_subtype(&_5views_info
);
483 * Register name for backwards compatibility with the
484 * wtap_filetypes table in Lua.
486 wtap_register_backwards_compatibility_lua_name("5VIEWS",
487 _5views_file_type_subtype
);
491 * Editor modelines - https://www.wireshark.org/tools/modelines.html
496 * indent-tabs-mode: t
499 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
500 * :indentSize=8:tabSize=8:noTabs=false: