Revert "UNUSED enc_key_id_{equal,hash}"
[wireshark-sm.git] / wiretap / iptrace.c
blobf031eb7c614a19237230d4bc0b18bb6735c21114
1 /* iptrace.c
3 * Wiretap Library
4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9 #include "config.h"
10 #include "iptrace.h"
12 #include <stdlib.h>
13 #include <string.h>
14 #include "wtap-int.h"
15 #include "file_wrappers.h"
16 #include "atm.h"
19 * Private per-wtap_t data needed to read a file.
21 typedef struct {
22 GHashTable *interface_ids; /* map name/description/link-layer type to interface ID */
23 unsigned num_interface_ids; /* Number of interface IDs assigned */
24 } iptrace_t;
26 #define IPTRACE_IFT_HF 0x3d /* Support for PERCS IP-HFI*/
27 #define IPTRACE_IFT_IB 0xc7 /* IP over Infiniband. Number by IANA */
29 static void iptrace_close(wtap *wth);
31 static bool iptrace_read_1_0(wtap *wth, wtap_rec *rec,
32 Buffer *buf, int *err, char **err_info, int64_t *data_offset);
33 static bool iptrace_seek_read_1_0(wtap *wth, int64_t seek_off,
34 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
36 static bool iptrace_read_2_0(wtap *wth, wtap_rec *rec,
37 Buffer *buf, int *err, char **err_info, int64_t *data_offset);
38 static bool iptrace_seek_read_2_0(wtap *wth, int64_t seek_off,
39 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
41 static bool iptrace_read_rec_data(FILE_T fh, Buffer *buf,
42 wtap_rec *rec, int *err, char **err_info);
43 static void fill_in_pseudo_header(int encap,
44 union wtap_pseudo_header *pseudo_header, const char *pkt_text);
45 static int wtap_encap_ift(unsigned int ift);
48 * Size of the version string in the file header.
50 #define VERSION_STRING_SIZE 11
53 * Hash table to map interface name and description, and link-layer
54 * type, to interface ID.
56 #define PREFIX_SIZE 4
58 typedef struct {
59 char prefix[PREFIX_SIZE+1];
60 uint8_t unit;
61 uint8_t if_type;
62 } if_info;
64 static int iptrace_1_0_file_type_subtype = -1;
65 static int iptrace_2_0_file_type_subtype = -1;
67 void register_iptrace(void);
69 static gboolean destroy_if_info(void *key, void *value _U_,
70 void *user_data _U_)
72 if_info *info = (if_info *)key;
74 g_free(info);
76 return true;
79 static unsigned if_info_hash(const void *info_arg)
81 if_info *info = (if_info *)info_arg;
83 return g_str_hash(info->prefix) + info->unit + info->if_type;
86 static gboolean if_info_equal(const void *info1_arg, const void *info2_arg)
88 if_info *info1 = (if_info *)info1_arg;
89 if_info *info2 = (if_info *)info2_arg;
91 return strcmp(info1->prefix, info2->prefix) == 0 &&
92 info1->unit == info2->unit &&
93 info1->if_type == info2->if_type;
96 wtap_open_return_val iptrace_open(wtap *wth, int *err, char **err_info)
98 char version_string[VERSION_STRING_SIZE+1];
99 iptrace_t *iptrace;
101 if (!wtap_read_bytes(wth->fh, version_string, VERSION_STRING_SIZE,
102 err, err_info)) {
103 if (*err != WTAP_ERR_SHORT_READ)
104 return WTAP_OPEN_ERROR;
105 return WTAP_OPEN_NOT_MINE;
107 version_string[VERSION_STRING_SIZE] = '\0';
109 if (strcmp(version_string, "iptrace 1.0") == 0) {
110 wth->file_type_subtype = iptrace_1_0_file_type_subtype;
111 wth->subtype_read = iptrace_read_1_0;
112 wth->subtype_seek_read = iptrace_seek_read_1_0;
113 wth->file_tsprec = WTAP_TSPREC_SEC;
115 else if (strcmp(version_string, "iptrace 2.0") == 0) {
116 wth->file_type_subtype = iptrace_2_0_file_type_subtype;
117 wth->subtype_read = iptrace_read_2_0;
118 wth->subtype_seek_read = iptrace_seek_read_2_0;
119 wth->file_tsprec = WTAP_TSPREC_NSEC;
121 else {
122 return WTAP_OPEN_NOT_MINE;
125 /* This is an iptrace file */
126 wth->subtype_close = iptrace_close;
127 iptrace = g_new(iptrace_t, 1);
128 iptrace->interface_ids = g_hash_table_new(if_info_hash, if_info_equal);
129 iptrace->num_interface_ids = 0;
130 wth->priv = (void *)iptrace;
132 return WTAP_OPEN_MINE;
135 static void iptrace_close(wtap *wth)
137 iptrace_t *iptrace = (iptrace_t *)wth->priv;
139 g_hash_table_foreach_remove(iptrace->interface_ids, destroy_if_info, NULL);
140 g_hash_table_destroy(iptrace->interface_ids);
143 static void add_new_if_info(iptrace_t *iptrace, if_info *info, void * *result)
145 if_info *new_info = g_new(if_info, 1);
146 *new_info = *info;
147 *result = GUINT_TO_POINTER(iptrace->num_interface_ids);
148 g_hash_table_insert(iptrace->interface_ids, (void *)new_info, *result);
149 iptrace->num_interface_ids++;
152 /***********************************************************
153 * iptrace 1.0 *
154 ***********************************************************/
157 * iptrace 1.0, discovered through inspection
159 * Packet record contains:
161 * an initial header, with a length field and a time stamp, in
162 * seconds since the Epoch;
164 * data, with the specified length.
166 * The data contains:
168 * a bunch of information about the packet;
170 * padding, at least for FDDI;
172 * the raw packet data.
176 * Offsets of fields in the initial header.
178 #define IPTRACE_1_0_REC_LENGTH_OFFSET 0 /* 0-3: size of record data */
179 #define IPTRACE_1_0_TV_SEC_OFFSET 4 /* 4-7: time stamp, seconds since the Epoch */
181 #define IPTRACE_1_0_PHDR_SIZE 8 /* initial header */
184 * Offsets of fields in the packet information.
186 /* Bytes 0-2 unknown */
187 #define IPTRACE_1_0_UNIT_OFFSET 3 /* 3: interface unit number */
188 #define IPTRACE_1_0_PREFIX_OFFSET 4 /* 4-7: null-terminated name prefix */
189 #define IPTRACE_1_0_PKT_TEXT_OFFSET 8 /* 8-19: text in 2.0; what is it in 1.0? */
190 #define IPTRACE_1_0_IF_TYPE_OFFSET 20 /* 20: SNMP ifType value */
191 #define IPTRACE_1_0_TX_FLAGS_OFFSET 21 /* 21: 0=receive, 1=transmit */
193 #define IPTRACE_1_0_PINFO_SIZE 22 /* packet information */
195 static bool
196 iptrace_read_rec_1_0(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
197 int *err, char **err_info)
199 iptrace_t *iptrace = (iptrace_t *)wth->priv;
200 uint8_t header[IPTRACE_1_0_PHDR_SIZE];
201 uint32_t record_length;
202 uint8_t pkt_info[IPTRACE_1_0_PINFO_SIZE];
203 if_info info;
204 uint32_t packet_size;
205 void *result;
207 if (!wtap_read_bytes_or_eof(fh, header, IPTRACE_1_0_PHDR_SIZE, err,
208 err_info)) {
209 /* Read error or EOF */
210 return false;
213 /* Get the record length */
214 record_length = pntoh32(&header[IPTRACE_1_0_REC_LENGTH_OFFSET]);
215 if (record_length < IPTRACE_1_0_PINFO_SIZE) {
217 * Uh-oh, the record isn't big enough to even have a
218 * packet information header.
220 *err = WTAP_ERR_BAD_FILE;
221 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet information header",
222 record_length);
223 return false;
227 * Get the packet information.
229 if (!wtap_read_bytes(fh, pkt_info, IPTRACE_1_0_PINFO_SIZE, err,
230 err_info)) {
231 /* Read error or EOF */
232 return false;
236 * The if_type field of the frame header appears to be an SNMP
237 * ifType value giving the type of the interface. Check out the
238 * <net/if_types.h> header file.
240 info.if_type = pkt_info[IPTRACE_1_0_IF_TYPE_OFFSET];
241 rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(info.if_type);
242 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_UNKNOWN) {
243 *err = WTAP_ERR_UNSUPPORTED;
244 *err_info = ws_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
245 info.if_type);
246 return false;
249 /* Get the packet data size */
250 packet_size = record_length - IPTRACE_1_0_PINFO_SIZE;
253 * AIX appears to put 3 bytes of padding in front of FDDI
254 * frames; strip that crap off.
256 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
258 * The packet size is really a record size and includes
259 * the padding.
261 if (packet_size < 3) {
263 * Uh-oh, the record isn't big enough to even have
264 * the padding.
266 *err = WTAP_ERR_BAD_FILE;
267 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
268 record_length);
269 return false;
271 packet_size -= 3;
274 * Skip the padding.
276 if (!wtap_read_bytes(fh, NULL, 3, err, err_info))
277 return false;
279 if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
281 * Probably a corrupt capture file; don't blow up trying
282 * to allocate space for an immensely-large packet.
284 *err = WTAP_ERR_BAD_FILE;
285 *err_info = ws_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
286 packet_size, WTAP_MAX_PACKET_SIZE_STANDARD);
287 return false;
290 rec->rec_type = REC_TYPE_PACKET;
291 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
292 rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_INTERFACE_ID;
293 rec->rec_header.packet_header.len = packet_size;
294 rec->rec_header.packet_header.caplen = packet_size;
295 rec->ts.secs = pntoh32(&header[IPTRACE_1_0_TV_SEC_OFFSET]);
296 rec->ts.nsecs = 0;
297 wtap_block_add_uint32_option(rec->block, OPT_PKT_FLAGS,
298 pkt_info[IPTRACE_1_0_TX_FLAGS_OFFSET] ?
299 (PACK_FLAGS_DIRECTION_OUTBOUND << PACK_FLAGS_DIRECTION_SHIFT) :
300 (PACK_FLAGS_DIRECTION_INBOUND << PACK_FLAGS_DIRECTION_SHIFT));
302 /* Fill in the pseudo-header. */
303 fill_in_pseudo_header(rec->rec_header.packet_header.pkt_encap,
304 &rec->rec_header.packet_header.pseudo_header,
305 (const char *)&pkt_info[IPTRACE_1_0_PKT_TEXT_OFFSET]);
307 /* Get the packet data */
308 if (!iptrace_read_rec_data(fh, buf, rec, err, err_info))
309 return false;
312 * No errors - get the interface ID.
314 * We do *not* trust the name to be null-terminated.
316 memcpy(info.prefix, &pkt_info[IPTRACE_1_0_PREFIX_OFFSET],
317 sizeof info.prefix);
318 info.prefix[PREFIX_SIZE] = '\0';
319 info.unit = pkt_info[IPTRACE_1_0_UNIT_OFFSET];
322 * Try to find the entry with that name, description, and
323 * interface type.
325 if (!g_hash_table_lookup_extended(iptrace->interface_ids,
326 (const void *)&info, NULL, &result)) {
327 wtap_block_t int_data;
328 wtapng_if_descr_mandatory_t *int_data_mand;
331 * Not found; make a new entry.
333 add_new_if_info(iptrace, &info, &result);
336 * Now make a new IDB and add it.
338 int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
339 int_data_mand = (wtapng_if_descr_mandatory_t *)wtap_block_get_mandatory_data(int_data);
341 int_data_mand->wtap_encap = rec->rec_header.packet_header.pkt_encap;
342 int_data_mand->tsprecision = WTAP_TSPREC_SEC;
343 int_data_mand->time_units_per_second = 1; /* No fractional time stamp */
344 int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD; /* XXX - not known */
346 wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0); /* 1-second resolution */
347 /* Interface statistics */
348 int_data_mand->num_stat_entries = 0;
349 int_data_mand->interface_statistics = NULL;
351 wtap_block_set_string_option_value_format(int_data,
352 OPT_IDB_NAME, "%s%u", info.prefix, info.unit);
353 wtap_add_idb(wth, int_data);
355 rec->rec_header.packet_header.interface_id = GPOINTER_TO_UINT(result);
356 return true;
359 /* Read the next packet */
360 static bool iptrace_read_1_0(wtap *wth, wtap_rec *rec,
361 Buffer *buf, int *err, char **err_info, int64_t *data_offset)
363 *data_offset = file_tell(wth->fh);
365 /* Read the packet */
366 if (!iptrace_read_rec_1_0(wth, wth->fh, rec, buf, err, err_info)) {
367 /* Read error or EOF */
368 return false;
371 /* If the per-file encapsulation isn't known, set it to this
372 packet's encapsulation.
374 If it *is* known, and it isn't this packet's encapsulation,
375 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
376 have a single encapsulation for all packets in the file. */
377 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
378 wth->file_encap = rec->rec_header.packet_header.pkt_encap;
379 else {
380 if (wth->file_encap != rec->rec_header.packet_header.pkt_encap)
381 wth->file_encap = WTAP_ENCAP_PER_PACKET;
384 return true;
387 static bool iptrace_seek_read_1_0(wtap *wth, int64_t seek_off,
388 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
390 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
391 return false;
393 /* Read the packet */
394 if (!iptrace_read_rec_1_0(wth, wth->random_fh, rec, buf, err,
395 err_info)) {
396 if (*err == 0)
397 *err = WTAP_ERR_SHORT_READ;
398 return false;
400 return true;
403 /***********************************************************
404 * iptrace 2.0 *
405 ***********************************************************/
408 * iptrace 2.0, discovered through inspection
410 * Packet record contains:
412 * an initial header, with a length field and a time stamp, in
413 * seconds since the Epoch;
415 * data, with the specified length.
417 * The data contains:
419 * a bunch of information about the packet;
421 * padding, at least for FDDI;
423 * the raw packet data.
427 * Offsets of fields in the initial header.
429 #define IPTRACE_2_0_REC_LENGTH_OFFSET 0 /* 0-3: size of record data */
430 #define IPTRACE_2_0_TV_SEC0_OFFSET 4 /* 4-7: time stamp, seconds since the Epoch */
432 #define IPTRACE_2_0_PHDR_SIZE 8 /* initial header */
435 * Offsets of fields in the packet information.
437 /* Bytes 0-2 unknown */
438 #define IPTRACE_2_0_UNIT_OFFSET 3 /* 3: interface unit number */
439 #define IPTRACE_2_0_PREFIX_OFFSET 4 /* 4-7: null-terminated name prefix */
440 #define IPTRACE_2_0_PKT_TEXT_OFFSET 8 /* 8-19: text stuff */
441 #define IPTRACE_2_0_IF_TYPE_OFFSET 20 /* 20: SNMP ifType value */
442 #define IPTRACE_2_0_TX_FLAGS_OFFSET 21 /* 21: 0=receive, 1=transmit */
443 /* Bytes 22-23 unknown */
444 #define IPTRACE_2_0_TV_SEC_OFFSET 24 /* 24-27: time stamp, seconds since the Epoch */
445 #define IPTRACE_2_0_TV_NSEC_OFFSET 28 /* 28-31: nanoseconds since that second */
447 #define IPTRACE_2_0_PINFO_SIZE 32 /* packet information */
449 static bool
450 iptrace_read_rec_2_0(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
451 int *err, char **err_info)
453 iptrace_t *iptrace = (iptrace_t *)wth->priv;
454 uint8_t header[IPTRACE_2_0_PHDR_SIZE];
455 uint32_t record_length;
456 uint8_t pkt_info[IPTRACE_2_0_PINFO_SIZE];
457 if_info info;
458 uint32_t packet_size;
459 void *result;
461 if (!wtap_read_bytes_or_eof(fh, header, IPTRACE_2_0_PHDR_SIZE, err,
462 err_info)) {
463 /* Read error or EOF */
464 return false;
467 /* Get the record length */
468 record_length = pntoh32(&header[IPTRACE_2_0_REC_LENGTH_OFFSET]);
469 if (record_length < IPTRACE_2_0_PINFO_SIZE) {
471 * Uh-oh, the record isn't big enough to even have a
472 * packet information header.
474 *err = WTAP_ERR_BAD_FILE;
475 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet information header",
476 record_length);
477 return false;
481 * Get the packet information.
483 if (!wtap_read_bytes(fh, pkt_info, IPTRACE_2_0_PINFO_SIZE, err,
484 err_info)) {
485 /* Read error or EOF */
486 return false;
490 * The if_type field of the frame header appears to be an SNMP
491 * ifType value giving the type of the interface. Check out the
492 * <net/if_types.h> header file.
494 info.if_type = pkt_info[IPTRACE_2_0_IF_TYPE_OFFSET];
495 rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(info.if_type);
496 #if 0
498 * We used to error out if the interface type in iptrace was
499 * unknown/unhandled, but an iptrace may contain packets
500 * from a variety of interfaces, some known, and others
501 * unknown.
503 * It is better to display the data even for unknown interface
504 * types, isntead of erroring out. In the future, it would be
505 * nice to be able to flag which frames are shown as data
506 * because their interface type is unknown, and also present
507 * the interface type number to the user so that it can be
508 * reported easily back to the Wireshark developer.
510 * XXX - what types are there that are used in files but
511 * that we don't handle?
513 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_UNKNOWN) {
514 *err = WTAP_ERR_UNSUPPORTED;
515 *err_info = ws_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
516 info.if_type);
517 return false;
519 #endif
521 /* Get the packet data size */
522 packet_size = record_length - IPTRACE_2_0_PINFO_SIZE;
525 * AIX appears to put 3 bytes of padding in front of FDDI
526 * frames; strip that crap off.
528 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
530 * The packet size is really a record size and includes
531 * the padding.
533 if (packet_size < 3) {
535 * Uh-oh, the record isn't big enough to even have
536 * the padding.
538 *err = WTAP_ERR_BAD_FILE;
539 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
540 record_length);
541 return false;
543 packet_size -= 3;
546 * Skip the padding.
548 if (!wtap_read_bytes(fh, NULL, 3, err, err_info))
549 return false;
551 if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
553 * Probably a corrupt capture file; don't blow up trying
554 * to allocate space for an immensely-large packet.
556 *err = WTAP_ERR_BAD_FILE;
557 *err_info = ws_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
558 packet_size, WTAP_MAX_PACKET_SIZE_STANDARD);
559 return false;
562 rec->rec_type = REC_TYPE_PACKET;
563 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
564 rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_INTERFACE_ID;
565 rec->rec_header.packet_header.len = packet_size;
566 rec->rec_header.packet_header.caplen = packet_size;
567 rec->ts.secs = pntoh32(&pkt_info[IPTRACE_2_0_TV_SEC_OFFSET]);
568 rec->ts.nsecs = pntoh32(&pkt_info[IPTRACE_2_0_TV_NSEC_OFFSET]);
569 wtap_block_add_uint32_option(rec->block, OPT_PKT_FLAGS,
570 pkt_info[IPTRACE_2_0_TX_FLAGS_OFFSET] ?
571 (PACK_FLAGS_DIRECTION_OUTBOUND << PACK_FLAGS_DIRECTION_SHIFT) :
572 (PACK_FLAGS_DIRECTION_INBOUND << PACK_FLAGS_DIRECTION_SHIFT));
574 /* Fill in the pseudo-header. */
575 fill_in_pseudo_header(rec->rec_header.packet_header.pkt_encap,
576 &rec->rec_header.packet_header.pseudo_header,
577 (const char *)&pkt_info[IPTRACE_1_0_PKT_TEXT_OFFSET]);
579 /* Get the packet data */
580 if (!iptrace_read_rec_data(fh, buf, rec, err, err_info))
581 return false;
584 * No errors - get the interface ID.
586 * We do *not* trust the name to be null-terminated.
588 memcpy(info.prefix, &pkt_info[IPTRACE_2_0_PREFIX_OFFSET],
589 sizeof info.prefix);
590 info.prefix[PREFIX_SIZE] = '\0';
591 info.unit = pkt_info[IPTRACE_2_0_UNIT_OFFSET];
594 * Try to find the entry with that name, description, and
595 * interface type.
597 if (!g_hash_table_lookup_extended(iptrace->interface_ids,
598 (const void *)&info, NULL, &result)) {
599 wtap_block_t int_data;
600 wtapng_if_descr_mandatory_t *int_data_mand;
603 * Not found; make a new entry.
605 add_new_if_info(iptrace, &info, &result);
608 * Now make a new IDB and add it.
610 int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
611 int_data_mand = (wtapng_if_descr_mandatory_t *)wtap_block_get_mandatory_data(int_data);
613 int_data_mand->wtap_encap = rec->rec_header.packet_header.pkt_encap;
614 int_data_mand->tsprecision = WTAP_TSPREC_NSEC;
615 int_data_mand->time_units_per_second = 1000000000; /* Nanosecond resolution */
616 int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD; /* XXX - not known */
618 wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0x09); /* nanosecond resolution */
619 /* Interface statistics */
620 int_data_mand->num_stat_entries = 0;
621 int_data_mand->interface_statistics = NULL;
623 wtap_block_set_string_option_value_format(int_data,
624 OPT_IDB_NAME, "%s%u", info.prefix, info.unit);
625 wtap_add_idb(wth, int_data);
627 rec->rec_header.packet_header.interface_id = GPOINTER_TO_UINT(result);
628 return true;
631 /* Read the next packet */
632 static bool iptrace_read_2_0(wtap *wth, wtap_rec *rec,
633 Buffer *buf, int *err, char **err_info, int64_t *data_offset)
635 *data_offset = file_tell(wth->fh);
637 /* Read the packet */
638 if (!iptrace_read_rec_2_0(wth, wth->fh, rec, buf, err, err_info)) {
639 /* Read error or EOF */
640 return false;
643 /* If the per-file encapsulation isn't known, set it to this
644 packet's encapsulation.
646 If it *is* known, and it isn't this packet's encapsulation,
647 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
648 have a single encapsulation for all packets in the file. */
649 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
650 wth->file_encap = rec->rec_header.packet_header.pkt_encap;
651 else {
652 if (wth->file_encap != rec->rec_header.packet_header.pkt_encap)
653 wth->file_encap = WTAP_ENCAP_PER_PACKET;
656 return true;
659 static bool iptrace_seek_read_2_0(wtap *wth, int64_t seek_off,
660 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
662 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
663 return false;
665 /* Read the packet */
666 if (!iptrace_read_rec_2_0(wth, wth->random_fh, rec, buf, err,
667 err_info)) {
668 if (*err == 0)
669 *err = WTAP_ERR_SHORT_READ;
670 return false;
672 return true;
675 static bool
676 iptrace_read_rec_data(FILE_T fh, Buffer *buf, wtap_rec *rec,
677 int *err, char **err_info)
679 if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
680 return false;
682 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ATM_PDUS) {
684 * Attempt to guess from the packet data, the VPI,
685 * and the VCI information about the type of traffic.
687 atm_guess_traffic_type(rec, ws_buffer_start_ptr(buf));
690 return true;
694 * Fill in the pseudo-header information we can.
696 * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic
697 * is in the packet - it was presumably run on a machine that was one of
698 * the endpoints of the connection, so in theory it could presumably have
699 * told us, but, for whatever reason, it failed to do so - perhaps the
700 * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't
701 * have access to that information (e.g., because it's in the ATM driver,
702 * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be
703 * handed up to some particular client, it doesn't know what that client is).
705 * We let our caller try to figure out what kind of traffic it is, either
706 * by guessing based on the VPI/VCI, guessing based on the header of the
707 * packet, seeing earlier traffic that set up the circuit and specified
708 * in some fashion what sort of traffic it is, or being told by the user.
710 static void
711 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
712 const char *pkt_text)
714 char if_text[9];
715 char *decimal;
716 int Vpi = 0;
717 int Vci = 0;
719 switch (encap) {
721 case WTAP_ENCAP_ATM_PDUS:
722 /* Rip apart the "x.y" text into Vpi/Vci numbers */
723 memcpy(if_text, &pkt_text[4], 8);
724 if_text[8] = '\0';
725 decimal = strchr(if_text, '.');
726 if (decimal) {
727 *decimal = '\0';
728 Vpi = (int)strtoul(if_text, NULL, 10);
729 decimal++;
730 Vci = (int)strtoul(decimal, NULL, 10);
734 * OK, which value means "DTE->DCE" and which value means
735 * "DCE->DTE"?
737 pseudo_header->atm.channel = pkt_text[13];
739 pseudo_header->atm.vpi = Vpi;
740 pseudo_header->atm.vci = Vci;
742 /* We don't have this information */
743 pseudo_header->atm.flags = 0;
744 pseudo_header->atm.cells = 0;
745 pseudo_header->atm.aal5t_u2u = 0;
746 pseudo_header->atm.aal5t_len = 0;
747 pseudo_header->atm.aal5t_chksum = 0;
748 break;
750 case WTAP_ENCAP_ETHERNET:
751 /* We assume there's no FCS in this frame. */
752 pseudo_header->eth.fcs_len = 0;
753 break;
757 /* Given an RFC1573 (SNMP ifType) interface type,
758 * return the appropriate Wiretap Encapsulation Type.
760 static int
761 wtap_encap_ift(unsigned int ift)
764 static const int ift_encap[] = {
765 /* 0x0 */ WTAP_ENCAP_UNKNOWN, /* nothing */
766 /* 0x1 */ WTAP_ENCAP_UNKNOWN, /* IFT_OTHER */
767 /* 0x2 */ WTAP_ENCAP_UNKNOWN, /* IFT_1822 */
768 /* 0x3 */ WTAP_ENCAP_UNKNOWN, /* IFT_HDH1822 */
769 /* 0x4 */ WTAP_ENCAP_RAW_IP, /* IFT_X25DDN */
770 /* 0x5 */ WTAP_ENCAP_UNKNOWN, /* IFT_X25 */
771 /* 0x6 */ WTAP_ENCAP_ETHERNET, /* IFT_ETHER */
772 /* 0x7 */ WTAP_ENCAP_ETHERNET, /* IFT_ISO88023 */
773 /* 0x8 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88024 */
774 /* 0x9 */ WTAP_ENCAP_TOKEN_RING, /* IFT_ISO88025 */
775 /* 0xa */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88026 */
776 /* 0xb */ WTAP_ENCAP_UNKNOWN, /* IFT_STARLAN */
777 /* 0xc */ WTAP_ENCAP_RAW_IP, /* IFT_P10, IBM SP switch */
778 /* 0xd */ WTAP_ENCAP_UNKNOWN, /* IFT_P80 */
779 /* 0xe */ WTAP_ENCAP_UNKNOWN, /* IFT_HY */
780 /* 0xf */ WTAP_ENCAP_FDDI_BITSWAPPED, /* IFT_FDDI */
781 /* 0x10 */ WTAP_ENCAP_LAPB, /* IFT_LAPB */ /* no data to back this up */
782 /* 0x11 */ WTAP_ENCAP_UNKNOWN, /* IFT_SDLC */
783 /* 0x12 */ WTAP_ENCAP_UNKNOWN, /* IFT_T1 */
784 /* 0x13 */ WTAP_ENCAP_UNKNOWN, /* IFT_CEPT */
785 /* 0x14 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNBASIC */
786 /* 0x15 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNPRIMARY */
787 /* 0x16 */ WTAP_ENCAP_UNKNOWN, /* IFT_PTPSERIAL */
788 /* 0x17 */ WTAP_ENCAP_UNKNOWN, /* IFT_PPP */
789 /* 0x18 */ WTAP_ENCAP_RAW_IP, /* IFT_LOOP */
790 /* 0x19 */ WTAP_ENCAP_UNKNOWN, /* IFT_EON */
791 /* 0x1a */ WTAP_ENCAP_UNKNOWN, /* IFT_XETHER */
792 /* 0x1b */ WTAP_ENCAP_UNKNOWN, /* IFT_NSIP */
793 /* 0x1c */ WTAP_ENCAP_UNKNOWN, /* IFT_SLIP */
794 /* 0x1d */ WTAP_ENCAP_UNKNOWN, /* IFT_ULTRA */
795 /* 0x1e */ WTAP_ENCAP_UNKNOWN, /* IFT_DS3 */
796 /* 0x1f */ WTAP_ENCAP_UNKNOWN, /* IFT_SIP */
797 /* 0x20 */ WTAP_ENCAP_UNKNOWN, /* IFT_FRELAY */
798 /* 0x21 */ WTAP_ENCAP_UNKNOWN, /* IFT_RS232 */
799 /* 0x22 */ WTAP_ENCAP_UNKNOWN, /* IFT_PARA */
800 /* 0x23 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNET */
801 /* 0x24 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNETPLUS */
802 /* 0x25 */ WTAP_ENCAP_ATM_PDUS, /* IFT_ATM */
804 #define NUM_IFT_ENCAPS array_length(ift_encap)
806 if (ift < NUM_IFT_ENCAPS) {
807 return ift_encap[ift];
809 else {
810 switch(ift) {
811 /* Infiniband*/
812 case IPTRACE_IFT_IB:
813 return WTAP_ENCAP_INFINIBAND;
815 /* Host Fabric Interface */
816 case IPTRACE_IFT_HF:
817 /* The HFI interface on AIX provides raw IP
818 in the packet trace. It's unclear if the HFI
819 can be configured for any other protocol, and if
820 any field in the iptrace header indicates what
821 that protocol is. For now, we are hard-coding
822 this as RAW_IP, but if we find another iptrace file
823 using HFI that provides another protocol, we will
824 have to figure out which field in the iptrace file
825 encodes it. */
826 return WTAP_ENCAP_RAW_IP;
828 default:
829 return WTAP_ENCAP_UNKNOWN;
834 /* Options for interface blocks. */
835 static const struct supported_option_type interface_block_options_supported[] = {
836 /* No comments, just an interface name. */
837 { OPT_IDB_NAME, ONE_OPTION_SUPPORTED }
840 static const struct supported_block_type iptrace_1_0_blocks_supported[] = {
842 * iptrace supports multiple interfaces, with descriptions, and
843 * supports associating packets with interfaces. Interface
844 * description blocks are used for that.
846 { WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
849 * iptrace is a capture format, so it obviously supports packets.
850 * It supports no packet options, however.
852 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
855 static const struct file_type_subtype_info iptrace_1_0_info = {
856 "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
857 false, BLOCKS_SUPPORTED(iptrace_1_0_blocks_supported),
858 NULL, NULL, NULL
861 static const struct supported_block_type iptrace_2_0_blocks_supported[] = {
863 * iptrace supports multiple interfaces, with descriptions, and
864 * supports associating packets with interfaces. Interface
865 * description blocks are used for that.
867 { WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
870 * iptrace is a capture format, so it obviously supports packets.
871 * It supports no packet options, however.
873 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
876 static const struct file_type_subtype_info iptrace_2_0_info = {
877 "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
878 false, BLOCKS_SUPPORTED(iptrace_2_0_blocks_supported),
879 NULL, NULL, NULL
882 void register_iptrace(void)
884 iptrace_1_0_file_type_subtype = wtap_register_file_type_subtype(&iptrace_1_0_info);
885 iptrace_2_0_file_type_subtype = wtap_register_file_type_subtype(&iptrace_2_0_info);
888 * Register names for backwards compatibility with the
889 * wtap_filetypes table in Lua.
891 wtap_register_backwards_compatibility_lua_name("IPTRACE_1_0",
892 iptrace_1_0_file_type_subtype);
893 wtap_register_backwards_compatibility_lua_name("IPTRACE_2_0",
894 iptrace_2_0_file_type_subtype);
898 * Editor modelines - https://www.wireshark.org/tools/modelines.html
900 * Local variables:
901 * c-basic-offset: 8
902 * tab-width: 8
903 * indent-tabs-mode: t
904 * End:
906 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
907 * :indentSize=8:tabSize=8:noTabs=false: