TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / wiretap / capsa.c
blob31057d109d5ad6d2886a46b598c120018c3d9c74
1 /* capsa.c
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
9 #include "config.h"
10 #include "capsa.h"
12 #include <string.h>
13 #include "wtap-int.h"
14 #include "file_wrappers.h"
15 #include <wsutil/ws_assert.h>
18 * A file begins with a header containing:
20 * a 4-byte magic number, with 'c', 'p', 's', 'e';
22 * either a 2-byte little-endian "format indicator" (version number?),
23 * or a 1-byte major version number followed by a 1-byte minor version
24 * number, or a 1-byte "format indicator" followed by something else
25 * that's always been 0;
27 * a 2-byte 0xe8 0x03 (1000 - a data rate? megabits/second?)
29 * 4 bytes of 0x01 0x00 0x01 0x00;
31 * either a 4-byte little-endian file size followed by 0x00 0x00 0x00 0x00
32 * or an 8-byte little-endian file size;
34 * a 4-byte little-endian packet count (in dns_error_of_udp, it exceeds?)
36 * a 4-byte little-endian number?
38 * hex 2c 01 c8 00 00 00 da 36 00 00 00 00 00 00;
40 * the same 4-byte little-endian number as above (yes, misaligned);
42 * 0x01 or 0x03;
44 * a bunch of 0s, up to an offset of 0x36d6;
46 * more stuff.
48 * Following that is a sequence of { record offset block, up to 200 records }
49 * pairs.
51 * A record offset block has 1 byte with the value 0xfe, a sequence of
52 * up to 200 4-byte little-endian record offsets, and 4 or more bytes
53 * of unknown data, making the block 805 bytes long.
55 * The record offsets are offsets, from the beginning of the record offset
56 * block (i.e., from the 0xfe byte), of the records following the block.
59 /* Magic number in Capsa files. */
60 static const char capsa_magic[] = {
61 'c', 'p', 's', 'e'
65 * Before each group of 200 or fewer records there's a block of frame
66 * offsets, giving the offsets, from the beginning of that block minus
67 * one(1), of the next N records.
69 #define N_RECORDS_PER_GROUP 200
71 /* Capsa (format indicator 1) record header. */
72 struct capsarec_hdr {
73 uint32_t unknown1; /* low-order 32 bits of a number? */
74 uint32_t unknown2; /* 0x00 0x00 0x00 0x00 */
75 uint32_t timestamplo; /* low-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
76 uint32_t timestamphi; /* high-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
77 uint16_t rec_len; /* length of record */
78 uint16_t incl_len; /* number of octets captured in file */
79 uint16_t orig_len; /* actual length of packet */
80 uint16_t unknown5; /* 0x00 0x00 */
81 uint8_t count1; /* count1*4 bytes after unknown8 */
82 uint8_t count2; /* count2*4 bytes after that */
83 uint16_t unknown7; /* 0x01 0x10 */
84 uint32_t unknown8; /* 0x00 0x00 0x00 0x00 or random numbers */
87 /* Packet Builder (format indicator 2) record header. */
88 struct pbrec_hdr {
89 uint16_t rec_len; /* length of record */
90 uint16_t incl_len; /* number of octets captured in file */
91 uint16_t orig_len; /* actual length of packet */
92 uint16_t unknown1;
93 uint16_t unknown2;
94 uint16_t unknown3;
95 uint32_t unknown4;
96 uint32_t timestamplo; /* low-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
97 uint32_t timestamphi; /* high-order 32 bits of the time stamp, in microseconds since January 1, 1970, 00:00:00 UTC */
98 uint32_t unknown5;
99 uint32_t unknown6;
102 typedef struct {
103 uint16_t format_indicator;
104 uint32_t number_of_frames;
105 uint32_t frame_count;
106 int64_t base_offset;
107 uint32_t record_offsets[N_RECORDS_PER_GROUP];
108 } capsa_t;
110 static bool capsa_read(wtap *wth, wtap_rec *rec, Buffer *buf,
111 int *err, char **err_info, int64_t *data_offset);
112 static bool capsa_seek_read(wtap *wth, int64_t seek_off,
113 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
114 static int capsa_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
115 Buffer *buf, int *err, char **err_info);
117 static int capsa_file_type_subtype = -1;
118 static int packet_builder_file_type_subtype = -1;
120 void register_capsa(void);
122 wtap_open_return_val capsa_open(wtap *wth, int *err, char **err_info)
124 char magic[sizeof capsa_magic];
125 uint16_t format_indicator;
126 int file_type_subtype;
127 uint32_t number_of_frames;
128 capsa_t *capsa;
130 /* Read in the string that should be at the start of a Capsa file */
131 if (!wtap_read_bytes(wth->fh, magic, sizeof magic, err, err_info)) {
132 if (*err != WTAP_ERR_SHORT_READ)
133 return WTAP_OPEN_ERROR;
134 return WTAP_OPEN_NOT_MINE;
137 if (memcmp(magic, capsa_magic, sizeof capsa_magic) != 0) {
138 return WTAP_OPEN_NOT_MINE;
141 /* Read the mysterious "format indicator" */
142 if (!wtap_read_bytes(wth->fh, &format_indicator, sizeof format_indicator,
143 err, err_info))
144 return WTAP_OPEN_ERROR;
145 format_indicator = GUINT16_FROM_LE(format_indicator);
148 * Make sure it's a format we support.
150 switch (format_indicator) {
152 case 1: /* Capsa */
153 file_type_subtype = capsa_file_type_subtype;
154 break;
156 case 2: /* Packet Builder */
157 file_type_subtype = packet_builder_file_type_subtype;
158 break;
160 default:
161 *err = WTAP_ERR_UNSUPPORTED;
162 *err_info = ws_strdup_printf("capsa: format indicator %u unsupported",
163 format_indicator);
164 return WTAP_OPEN_ERROR;
168 * Link speed, in megabytes/second?
170 if (!wtap_read_bytes(wth->fh, NULL, 2, err, err_info))
171 return WTAP_OPEN_ERROR;
174 * Flags of some sort? Four 1-byte numbers, two of which are 1
175 * and two of which are zero? Two 2-byte numbers or flag fields,
176 * both of which are 1?
178 if (!wtap_read_bytes(wth->fh, NULL, 4, err, err_info))
179 return WTAP_OPEN_ERROR;
182 * File size, in bytes.
184 if (!wtap_read_bytes(wth->fh, NULL, 4, err, err_info))
185 return WTAP_OPEN_ERROR;
188 * Zeroes? Or upper 4 bytes of file size?
190 if (!wtap_read_bytes(wth->fh, NULL, 4, err, err_info))
191 return WTAP_OPEN_ERROR;
194 * Count of packets.
196 if (!wtap_read_bytes(wth->fh, &number_of_frames, sizeof number_of_frames,
197 err, err_info))
198 return WTAP_OPEN_ERROR;
199 number_of_frames = GUINT32_FROM_LE(number_of_frames);
202 * Skip past what we think is file header.
204 if (!file_seek(wth->fh, 0x44ef, SEEK_SET, err))
205 return WTAP_OPEN_ERROR;
207 wth->file_type_subtype = file_type_subtype;
208 capsa = g_new(capsa_t, 1);
209 capsa->format_indicator = format_indicator;
210 capsa->number_of_frames = number_of_frames;
211 capsa->frame_count = 0;
212 wth->priv = (void *)capsa;
213 wth->subtype_read = capsa_read;
214 wth->subtype_seek_read = capsa_seek_read;
216 * XXX - we've never seen a Wi-Fi Capsa capture, so we don't
217 * yet know how to handle them.
219 wth->file_encap = WTAP_ENCAP_ETHERNET;
220 wth->snapshot_length = 0; /* not available in header */
221 wth->file_tsprec = WTAP_TSPREC_USEC;
224 * Add an IDB; we don't know how many interfaces were
225 * involved, so we just say one interface, about which
226 * we only know the link-layer type, snapshot length,
227 * and time stamp resolution.
229 wtap_add_generated_idb(wth);
231 return WTAP_OPEN_MINE;
234 /* Read the next packet */
235 static bool capsa_read(wtap *wth, wtap_rec *rec, Buffer *buf,
236 int *err, char **err_info, int64_t *data_offset)
238 capsa_t *capsa = (capsa_t *)wth->priv;
239 uint32_t frame_within_block;
240 int padbytes;
242 if (capsa->frame_count == capsa->number_of_frames) {
244 * No more frames left. Return an EOF.
246 *err = 0;
247 return false;
249 frame_within_block = capsa->frame_count % N_RECORDS_PER_GROUP;
250 if (frame_within_block == 0) {
252 * Here's a record offset block.
253 * Get the offset of the block, and then skip the
254 * first byte.
256 capsa->base_offset = file_tell(wth->fh);
257 if (!wtap_read_bytes(wth->fh, NULL, 1, err, err_info))
258 return false;
261 * Now read the record offsets.
263 if (!wtap_read_bytes(wth->fh, &capsa->record_offsets,
264 sizeof capsa->record_offsets, err, err_info))
265 return false;
268 * And finish processing all 805 bytes by skipping
269 * the last 4 bytes.
271 if (!wtap_read_bytes(wth->fh, NULL, 4, err, err_info))
272 return false;
275 *data_offset = capsa->base_offset +
276 GUINT32_FROM_LE(capsa->record_offsets[frame_within_block]);
277 if (!file_seek(wth->fh, *data_offset, SEEK_SET, err))
278 return false;
280 padbytes = capsa_read_packet(wth, wth->fh, rec, buf, err, err_info);
281 if (padbytes == -1)
282 return false;
285 * Skip over the padding, if any.
287 if (padbytes != 0) {
288 if (!wtap_read_bytes(wth->fh, NULL, padbytes, err, err_info))
289 return false;
292 capsa->frame_count++;
294 return true;
297 static bool
298 capsa_seek_read(wtap *wth, int64_t seek_off,
299 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
301 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
302 return false;
304 if (capsa_read_packet(wth, wth->random_fh, rec, buf, err, err_info) == -1) {
305 if (*err == 0)
306 *err = WTAP_ERR_SHORT_READ;
307 return false;
309 return true;
312 static int
313 capsa_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
314 Buffer *buf, int *err, char **err_info)
316 capsa_t *capsa = (capsa_t *)wth->priv;
317 struct capsarec_hdr capsarec_hdr;
318 struct pbrec_hdr pbrec_hdr;
319 uint32_t rec_size;
320 uint32_t packet_size;
321 uint32_t orig_size;
322 uint32_t header_size;
323 uint64_t timestamp;
325 /* Read record header. */
326 switch (capsa->format_indicator) {
328 case 1:
329 if (!wtap_read_bytes_or_eof(fh, &capsarec_hdr,
330 sizeof capsarec_hdr, err, err_info))
331 return -1;
332 rec_size = GUINT16_FROM_LE(capsarec_hdr.rec_len);
333 orig_size = GUINT16_FROM_LE(capsarec_hdr.orig_len);
334 packet_size = GUINT16_FROM_LE(capsarec_hdr.incl_len);
335 header_size = sizeof capsarec_hdr;
336 timestamp = (((uint64_t)GUINT32_FROM_LE(capsarec_hdr.timestamphi))<<32) + GUINT32_FROM_LE(capsarec_hdr.timestamplo);
339 * OK, the rest of this is variable-length.
340 * We skip: (count1+count2)*4 bytes.
341 * XXX - what is that? Measured statistics?
342 * Calculated statistics?
344 if (!wtap_read_bytes(fh, NULL,
345 (capsarec_hdr.count1 + capsarec_hdr.count2)*4,
346 err, err_info))
347 return -1;
348 header_size += (capsarec_hdr.count1 + capsarec_hdr.count2)*4;
349 break;
351 case 2:
352 if (!wtap_read_bytes_or_eof(fh, &pbrec_hdr,
353 sizeof pbrec_hdr, err, err_info))
354 return -1;
355 rec_size = GUINT16_FROM_LE(pbrec_hdr.rec_len);
356 orig_size = GUINT16_FROM_LE(pbrec_hdr.orig_len);
357 packet_size = GUINT16_FROM_LE(pbrec_hdr.incl_len);
358 header_size = sizeof pbrec_hdr;
359 timestamp = (((uint64_t)GUINT32_FROM_LE(pbrec_hdr.timestamphi))<<32) + GUINT32_FROM_LE(pbrec_hdr.timestamplo);
361 * XXX - from the results of some conversions between
362 * Capsa format and pcap by Colasoft Packet Builder,
363 * I do not trust its conversion of time stamps (at
364 * least one of Colasoft's sample files, when
365 * converted to pcap format, has, as its time stamps,
366 * time stamps on the day after the conversion was
367 * done, which seems like more than just coincidence).
369 break;
371 default:
372 ws_assert_not_reached();
373 *err = WTAP_ERR_INTERNAL;
374 *err_info = ws_strdup_printf("capsa: format indicator is %u", capsa->format_indicator);
375 return -1;
377 if (orig_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
379 * Probably a corrupt capture file; don't blow up trying
380 * to allocate space for an immensely-large packet.
382 *err = WTAP_ERR_BAD_FILE;
383 *err_info = ws_strdup_printf("capsa: File has %u-byte original length, bigger than maximum of %u",
384 orig_size, WTAP_MAX_PACKET_SIZE_STANDARD);
385 return -1;
387 if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
389 * Probably a corrupt capture file; don't blow up trying
390 * to allocate space for an immensely-large packet.
392 *err = WTAP_ERR_BAD_FILE;
393 *err_info = ws_strdup_printf("capsa: File has %u-byte packet, bigger than maximum of %u",
394 packet_size, WTAP_MAX_PACKET_SIZE_STANDARD);
395 return -1;
397 if (header_size + packet_size > rec_size) {
399 * Probably a corrupt capture file.
401 *err = WTAP_ERR_BAD_FILE;
402 *err_info = ws_strdup_printf("capsa: File has %u-byte packet with %u-byte record header, bigger than record size %u",
403 packet_size, header_size, rec_size);
404 return -1;
408 * The "on the wire" record size always includes the CRC.
409 * If it's greater than the "captured" size by 4, then
410 * we subtract 4 from it, to reflect the way the "on the wire"
411 * record size works for other file formats.
413 if (orig_size == packet_size + 4)
414 orig_size = packet_size;
417 * We assume there's no FCS in this frame.
418 * XXX - is there ever one?
420 rec->rec_header.packet_header.pseudo_header.eth.fcs_len = 0;
422 rec->rec_type = REC_TYPE_PACKET;
423 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
424 rec->rec_header.packet_header.caplen = packet_size;
425 rec->rec_header.packet_header.len = orig_size;
426 rec->presence_flags = WTAP_HAS_CAP_LEN|WTAP_HAS_TS;
427 rec->ts.secs = (time_t)(timestamp / 1000000);
428 rec->ts.nsecs = ((int)(timestamp % 1000000))*1000;
431 * Read the packet data.
433 if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
434 return -1; /* failed */
436 return rec_size - (header_size + packet_size);
439 static const struct supported_block_type capsa_blocks_supported[] = {
441 * We support packet blocks, with no comments or other options.
443 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
446 static const struct file_type_subtype_info capsa_info = {
447 "Colasoft Capsa format", "capsa", "cscpkt", NULL,
448 false, BLOCKS_SUPPORTED(capsa_blocks_supported),
449 NULL, NULL, NULL
452 static const struct supported_block_type packet_builder_blocks_supported[] = {
454 * We support packet blocks, with no comments or other options.
456 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
459 static const struct file_type_subtype_info packet_builder_info = {
460 "Colasoft Packet Builder format", "colasoft-pb", "cscpkt", NULL,
461 false, BLOCKS_SUPPORTED(packet_builder_blocks_supported),
462 NULL, NULL, NULL
465 void register_capsa(void)
467 capsa_file_type_subtype = wtap_register_file_type_subtype(&capsa_info);
468 packet_builder_file_type_subtype = wtap_register_file_type_subtype(&packet_builder_info);
471 * Register names for backwards compatibility with the
472 * wtap_filetypes table in Lua.
474 wtap_register_backwards_compatibility_lua_name("COLASOFT_CAPSA",
475 capsa_file_type_subtype);
476 wtap_register_backwards_compatibility_lua_name("COLASOFT_PACKET_BUILDER",
477 packet_builder_file_type_subtype);
481 * Editor modelines - https://www.wireshark.org/tools/modelines.html
483 * Local variables:
484 * c-basic-offset: 8
485 * tab-width: 8
486 * indent-tabs-mode: t
487 * End:
489 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
490 * :indentSize=8:tabSize=8:noTabs=false: