kerberos: remember account details from dissect_krb5_PAC_UPN_DNS_INFO on EncTicketPar...
[wireshark-sm.git] / wiretap / iptrace.c
blob80d5a40c2d4dbbe7a12c003901a739b0e0c2f874
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 <stdlib.h>
11 #include <string.h>
12 #include "wtap-int.h"
13 #include "file_wrappers.h"
14 #include "atm.h"
15 #include "iptrace.h"
18 * Private per-wtap_t data needed to read a file.
20 typedef struct {
21 GHashTable *interface_ids; /* map name/description/link-layer type to interface ID */
22 unsigned num_interface_ids; /* Number of interface IDs assigned */
23 } iptrace_t;
25 #define IPTRACE_IFT_HF 0x3d /* Support for PERCS IP-HFI*/
26 #define IPTRACE_IFT_IB 0xc7 /* IP over Infiniband. Number by IANA */
28 static void iptrace_close(wtap *wth);
30 static bool iptrace_read_1_0(wtap *wth, wtap_rec *rec,
31 Buffer *buf, int *err, char **err_info, int64_t *data_offset);
32 static bool iptrace_seek_read_1_0(wtap *wth, int64_t seek_off,
33 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
35 static bool iptrace_read_2_0(wtap *wth, wtap_rec *rec,
36 Buffer *buf, int *err, char **err_info, int64_t *data_offset);
37 static bool iptrace_seek_read_2_0(wtap *wth, int64_t seek_off,
38 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
40 static bool iptrace_read_rec_data(FILE_T fh, Buffer *buf,
41 wtap_rec *rec, int *err, char **err_info);
42 static void fill_in_pseudo_header(int encap,
43 union wtap_pseudo_header *pseudo_header, const char *pkt_text);
44 static int wtap_encap_ift(unsigned int ift);
47 * Size of the version string in the file header.
49 #define VERSION_STRING_SIZE 11
52 * Hash table to map interface name and description, and link-layer
53 * type, to interface ID.
55 #define PREFIX_SIZE 4
57 typedef struct {
58 char prefix[PREFIX_SIZE+1];
59 uint8_t unit;
60 uint8_t if_type;
61 } if_info;
63 static int iptrace_1_0_file_type_subtype = -1;
64 static int iptrace_2_0_file_type_subtype = -1;
66 void register_iptrace(void);
68 static gboolean destroy_if_info(void *key, void *value _U_,
69 void *user_data _U_)
71 if_info *info = (if_info *)key;
73 g_free(info);
75 return true;
78 static unsigned if_info_hash(gconstpointer info_arg)
80 if_info *info = (if_info *)info_arg;
82 return g_str_hash(info->prefix) + info->unit + info->if_type;
85 static gboolean if_info_equal(gconstpointer info1_arg, gconstpointer info2_arg)
87 if_info *info1 = (if_info *)info1_arg;
88 if_info *info2 = (if_info *)info2_arg;
90 return strcmp(info1->prefix, info2->prefix) == 0 &&
91 info1->unit == info2->unit &&
92 info1->if_type == info2->if_type;
95 wtap_open_return_val iptrace_open(wtap *wth, int *err, char **err_info)
97 char version_string[VERSION_STRING_SIZE+1];
98 iptrace_t *iptrace;
100 if (!wtap_read_bytes(wth->fh, version_string, VERSION_STRING_SIZE,
101 err, err_info)) {
102 if (*err != WTAP_ERR_SHORT_READ)
103 return WTAP_OPEN_ERROR;
104 return WTAP_OPEN_NOT_MINE;
106 version_string[VERSION_STRING_SIZE] = '\0';
108 if (strcmp(version_string, "iptrace 1.0") == 0) {
109 wth->file_type_subtype = iptrace_1_0_file_type_subtype;
110 wth->subtype_read = iptrace_read_1_0;
111 wth->subtype_seek_read = iptrace_seek_read_1_0;
112 wth->file_tsprec = WTAP_TSPREC_SEC;
114 else if (strcmp(version_string, "iptrace 2.0") == 0) {
115 wth->file_type_subtype = iptrace_2_0_file_type_subtype;
116 wth->subtype_read = iptrace_read_2_0;
117 wth->subtype_seek_read = iptrace_seek_read_2_0;
118 wth->file_tsprec = WTAP_TSPREC_NSEC;
120 else {
121 return WTAP_OPEN_NOT_MINE;
124 /* This is an iptrace file */
125 wth->subtype_close = iptrace_close;
126 iptrace = g_new(iptrace_t, 1);
127 iptrace->interface_ids = g_hash_table_new(if_info_hash, if_info_equal);
128 iptrace->num_interface_ids = 0;
129 wth->priv = (void *)iptrace;
131 return WTAP_OPEN_MINE;
134 static void iptrace_close(wtap *wth)
136 iptrace_t *iptrace = (iptrace_t *)wth->priv;
138 g_hash_table_foreach_remove(iptrace->interface_ids, destroy_if_info, NULL);
139 g_hash_table_destroy(iptrace->interface_ids);
142 static void add_new_if_info(iptrace_t *iptrace, if_info *info, void * *result)
144 if_info *new_info = g_new(if_info, 1);
145 *new_info = *info;
146 *result = GUINT_TO_POINTER(iptrace->num_interface_ids);
147 g_hash_table_insert(iptrace->interface_ids, (void *)new_info, *result);
148 iptrace->num_interface_ids++;
151 /***********************************************************
152 * iptrace 1.0 *
153 ***********************************************************/
156 * iptrace 1.0, discovered through inspection
158 * Packet record contains:
160 * an initial header, with a length field and a time stamp, in
161 * seconds since the Epoch;
163 * data, with the specified length.
165 * The data contains:
167 * a bunch of information about the packet;
169 * padding, at least for FDDI;
171 * the raw packet data.
175 * Offsets of fields in the initial header.
177 #define IPTRACE_1_0_REC_LENGTH_OFFSET 0 /* 0-3: size of record data */
178 #define IPTRACE_1_0_TV_SEC_OFFSET 4 /* 4-7: time stamp, seconds since the Epoch */
180 #define IPTRACE_1_0_PHDR_SIZE 8 /* initial header */
183 * Offsets of fields in the packet information.
185 /* Bytes 0-2 unknown */
186 #define IPTRACE_1_0_UNIT_OFFSET 3 /* 3: interface unit number */
187 #define IPTRACE_1_0_PREFIX_OFFSET 4 /* 4-7: null-terminated name prefix */
188 #define IPTRACE_1_0_PKT_TEXT_OFFSET 8 /* 8-19: text in 2.0; what is it in 1.0? */
189 #define IPTRACE_1_0_IF_TYPE_OFFSET 20 /* 20: SNMP ifType value */
190 #define IPTRACE_1_0_TX_FLAGS_OFFSET 21 /* 21: 0=receive, 1=transmit */
192 #define IPTRACE_1_0_PINFO_SIZE 22 /* packet information */
194 static bool
195 iptrace_read_rec_1_0(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
196 int *err, char **err_info)
198 iptrace_t *iptrace = (iptrace_t *)wth->priv;
199 uint8_t header[IPTRACE_1_0_PHDR_SIZE];
200 uint32_t record_length;
201 uint8_t pkt_info[IPTRACE_1_0_PINFO_SIZE];
202 if_info info;
203 uint32_t packet_size;
204 void *result;
206 if (!wtap_read_bytes_or_eof(fh, header, IPTRACE_1_0_PHDR_SIZE, err,
207 err_info)) {
208 /* Read error or EOF */
209 return false;
212 /* Get the record length */
213 record_length = pntoh32(&header[IPTRACE_1_0_REC_LENGTH_OFFSET]);
214 if (record_length < IPTRACE_1_0_PINFO_SIZE) {
216 * Uh-oh, the record isn't big enough to even have a
217 * packet information header.
219 *err = WTAP_ERR_BAD_FILE;
220 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet information header",
221 record_length);
222 return false;
226 * Get the packet information.
228 if (!wtap_read_bytes(fh, pkt_info, IPTRACE_1_0_PINFO_SIZE, err,
229 err_info)) {
230 /* Read error or EOF */
231 return false;
235 * The if_type field of the frame header appears to be an SNMP
236 * ifType value giving the type of the interface. Check out the
237 * <net/if_types.h> header file.
239 info.if_type = pkt_info[IPTRACE_1_0_IF_TYPE_OFFSET];
240 rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(info.if_type);
241 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_UNKNOWN) {
242 *err = WTAP_ERR_UNSUPPORTED;
243 *err_info = ws_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
244 info.if_type);
245 return false;
248 /* Get the packet data size */
249 packet_size = record_length - IPTRACE_1_0_PINFO_SIZE;
252 * AIX appears to put 3 bytes of padding in front of FDDI
253 * frames; strip that crap off.
255 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
257 * The packet size is really a record size and includes
258 * the padding.
260 if (packet_size < 3) {
262 * Uh-oh, the record isn't big enough to even have
263 * the padding.
265 *err = WTAP_ERR_BAD_FILE;
266 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
267 record_length);
268 return false;
270 packet_size -= 3;
273 * Skip the padding.
275 if (!wtap_read_bytes(fh, NULL, 3, err, err_info))
276 return false;
278 if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
280 * Probably a corrupt capture file; don't blow up trying
281 * to allocate space for an immensely-large packet.
283 *err = WTAP_ERR_BAD_FILE;
284 *err_info = ws_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
285 packet_size, WTAP_MAX_PACKET_SIZE_STANDARD);
286 return false;
289 rec->rec_type = REC_TYPE_PACKET;
290 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
291 rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_INTERFACE_ID;
292 rec->rec_header.packet_header.len = packet_size;
293 rec->rec_header.packet_header.caplen = packet_size;
294 rec->ts.secs = pntoh32(&header[IPTRACE_1_0_TV_SEC_OFFSET]);
295 rec->ts.nsecs = 0;
296 wtap_block_add_uint32_option(rec->block, OPT_PKT_FLAGS,
297 pkt_info[IPTRACE_1_0_TX_FLAGS_OFFSET] ?
298 (PACK_FLAGS_DIRECTION_OUTBOUND << PACK_FLAGS_DIRECTION_SHIFT) :
299 (PACK_FLAGS_DIRECTION_INBOUND << PACK_FLAGS_DIRECTION_SHIFT));
301 /* Fill in the pseudo-header. */
302 fill_in_pseudo_header(rec->rec_header.packet_header.pkt_encap,
303 &rec->rec_header.packet_header.pseudo_header,
304 (const char *)&pkt_info[IPTRACE_1_0_PKT_TEXT_OFFSET]);
306 /* Get the packet data */
307 if (!iptrace_read_rec_data(fh, buf, rec, err, err_info))
308 return false;
311 * No errors - get the interface ID.
313 * We do *not* trust the name to be null-terminated.
315 memcpy(info.prefix, &pkt_info[IPTRACE_1_0_PREFIX_OFFSET],
316 sizeof info.prefix);
317 info.prefix[PREFIX_SIZE] = '\0';
318 info.unit = pkt_info[IPTRACE_1_0_UNIT_OFFSET];
321 * Try to find the entry with that name, description, and
322 * interface type.
324 if (!g_hash_table_lookup_extended(iptrace->interface_ids,
325 (gconstpointer)&info, NULL, &result)) {
326 wtap_block_t int_data;
327 wtapng_if_descr_mandatory_t *int_data_mand;
330 * Not found; make a new entry.
332 add_new_if_info(iptrace, &info, &result);
335 * Now make a new IDB and add it.
337 int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
338 int_data_mand = (wtapng_if_descr_mandatory_t *)wtap_block_get_mandatory_data(int_data);
340 int_data_mand->wtap_encap = rec->rec_header.packet_header.pkt_encap;
341 int_data_mand->tsprecision = WTAP_TSPREC_SEC;
342 int_data_mand->time_units_per_second = 1; /* No fractional time stamp */
343 int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD; /* XXX - not known */
345 wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0); /* 1-second resolution */
346 /* Interface statistics */
347 int_data_mand->num_stat_entries = 0;
348 int_data_mand->interface_statistics = NULL;
350 wtap_block_set_string_option_value_format(int_data,
351 OPT_IDB_NAME, "%s%u", info.prefix, info.unit);
352 wtap_add_idb(wth, int_data);
354 rec->rec_header.packet_header.interface_id = GPOINTER_TO_UINT(result);
355 return true;
358 /* Read the next packet */
359 static bool iptrace_read_1_0(wtap *wth, wtap_rec *rec,
360 Buffer *buf, int *err, char **err_info, int64_t *data_offset)
362 *data_offset = file_tell(wth->fh);
364 /* Read the packet */
365 if (!iptrace_read_rec_1_0(wth, wth->fh, rec, buf, err, err_info)) {
366 /* Read error or EOF */
367 return false;
370 /* If the per-file encapsulation isn't known, set it to this
371 packet's encapsulation.
373 If it *is* known, and it isn't this packet's encapsulation,
374 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
375 have a single encapsulation for all packets in the file. */
376 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
377 wth->file_encap = rec->rec_header.packet_header.pkt_encap;
378 else {
379 if (wth->file_encap != rec->rec_header.packet_header.pkt_encap)
380 wth->file_encap = WTAP_ENCAP_PER_PACKET;
383 return true;
386 static bool iptrace_seek_read_1_0(wtap *wth, int64_t seek_off,
387 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
389 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
390 return false;
392 /* Read the packet */
393 if (!iptrace_read_rec_1_0(wth, wth->random_fh, rec, buf, err,
394 err_info)) {
395 if (*err == 0)
396 *err = WTAP_ERR_SHORT_READ;
397 return false;
399 return true;
402 /***********************************************************
403 * iptrace 2.0 *
404 ***********************************************************/
407 * iptrace 2.0, discovered through inspection
409 * Packet record contains:
411 * an initial header, with a length field and a time stamp, in
412 * seconds since the Epoch;
414 * data, with the specified length.
416 * The data contains:
418 * a bunch of information about the packet;
420 * padding, at least for FDDI;
422 * the raw packet data.
426 * Offsets of fields in the initial header.
428 #define IPTRACE_2_0_REC_LENGTH_OFFSET 0 /* 0-3: size of record data */
429 #define IPTRACE_2_0_TV_SEC0_OFFSET 4 /* 4-7: time stamp, seconds since the Epoch */
431 #define IPTRACE_2_0_PHDR_SIZE 8 /* initial header */
434 * Offsets of fields in the packet information.
436 /* Bytes 0-2 unknown */
437 #define IPTRACE_2_0_UNIT_OFFSET 3 /* 3: interface unit number */
438 #define IPTRACE_2_0_PREFIX_OFFSET 4 /* 4-7: null-terminated name prefix */
439 #define IPTRACE_2_0_PKT_TEXT_OFFSET 8 /* 8-19: text stuff */
440 #define IPTRACE_2_0_IF_TYPE_OFFSET 20 /* 20: SNMP ifType value */
441 #define IPTRACE_2_0_TX_FLAGS_OFFSET 21 /* 21: 0=receive, 1=transmit */
442 /* Bytes 22-23 unknown */
443 #define IPTRACE_2_0_TV_SEC_OFFSET 24 /* 24-27: time stamp, seconds since the Epoch */
444 #define IPTRACE_2_0_TV_NSEC_OFFSET 28 /* 28-31: nanoseconds since that second */
446 #define IPTRACE_2_0_PINFO_SIZE 32 /* packet information */
448 static bool
449 iptrace_read_rec_2_0(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf,
450 int *err, char **err_info)
452 iptrace_t *iptrace = (iptrace_t *)wth->priv;
453 uint8_t header[IPTRACE_2_0_PHDR_SIZE];
454 uint32_t record_length;
455 uint8_t pkt_info[IPTRACE_2_0_PINFO_SIZE];
456 if_info info;
457 uint32_t packet_size;
458 void *result;
460 if (!wtap_read_bytes_or_eof(fh, header, IPTRACE_2_0_PHDR_SIZE, err,
461 err_info)) {
462 /* Read error or EOF */
463 return false;
466 /* Get the record length */
467 record_length = pntoh32(&header[IPTRACE_2_0_REC_LENGTH_OFFSET]);
468 if (record_length < IPTRACE_2_0_PINFO_SIZE) {
470 * Uh-oh, the record isn't big enough to even have a
471 * packet information header.
473 *err = WTAP_ERR_BAD_FILE;
474 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet information header",
475 record_length);
476 return false;
480 * Get the packet information.
482 if (!wtap_read_bytes(fh, pkt_info, IPTRACE_2_0_PINFO_SIZE, err,
483 err_info)) {
484 /* Read error or EOF */
485 return false;
489 * The if_type field of the frame header appears to be an SNMP
490 * ifType value giving the type of the interface. Check out the
491 * <net/if_types.h> header file.
493 info.if_type = pkt_info[IPTRACE_2_0_IF_TYPE_OFFSET];
494 rec->rec_header.packet_header.pkt_encap = wtap_encap_ift(info.if_type);
495 #if 0
497 * We used to error out if the interface type in iptrace was
498 * unknown/unhandled, but an iptrace may contain packets
499 * from a variety of interfaces, some known, and others
500 * unknown.
502 * It is better to display the data even for unknown interface
503 * types, isntead of erroring out. In the future, it would be
504 * nice to be able to flag which frames are shown as data
505 * because their interface type is unknown, and also present
506 * the interface type number to the user so that it can be
507 * reported easily back to the Wireshark developer.
509 * XXX - what types are there that are used in files but
510 * that we don't handle?
512 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_UNKNOWN) {
513 *err = WTAP_ERR_UNSUPPORTED;
514 *err_info = ws_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
515 info.if_type);
516 return false;
518 #endif
520 /* Get the packet data size */
521 packet_size = record_length - IPTRACE_2_0_PINFO_SIZE;
524 * AIX appears to put 3 bytes of padding in front of FDDI
525 * frames; strip that crap off.
527 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
529 * The packet size is really a record size and includes
530 * the padding.
532 if (packet_size < 3) {
534 * Uh-oh, the record isn't big enough to even have
535 * the padding.
537 *err = WTAP_ERR_BAD_FILE;
538 *err_info = ws_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
539 record_length);
540 return false;
542 packet_size -= 3;
545 * Skip the padding.
547 if (!wtap_read_bytes(fh, NULL, 3, err, err_info))
548 return false;
550 if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD) {
552 * Probably a corrupt capture file; don't blow up trying
553 * to allocate space for an immensely-large packet.
555 *err = WTAP_ERR_BAD_FILE;
556 *err_info = ws_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
557 packet_size, WTAP_MAX_PACKET_SIZE_STANDARD);
558 return false;
561 rec->rec_type = REC_TYPE_PACKET;
562 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
563 rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_INTERFACE_ID;
564 rec->rec_header.packet_header.len = packet_size;
565 rec->rec_header.packet_header.caplen = packet_size;
566 rec->ts.secs = pntoh32(&pkt_info[IPTRACE_2_0_TV_SEC_OFFSET]);
567 rec->ts.nsecs = pntoh32(&pkt_info[IPTRACE_2_0_TV_NSEC_OFFSET]);
568 wtap_block_add_uint32_option(rec->block, OPT_PKT_FLAGS,
569 pkt_info[IPTRACE_2_0_TX_FLAGS_OFFSET] ?
570 (PACK_FLAGS_DIRECTION_OUTBOUND << PACK_FLAGS_DIRECTION_SHIFT) :
571 (PACK_FLAGS_DIRECTION_INBOUND << PACK_FLAGS_DIRECTION_SHIFT));
573 /* Fill in the pseudo-header. */
574 fill_in_pseudo_header(rec->rec_header.packet_header.pkt_encap,
575 &rec->rec_header.packet_header.pseudo_header,
576 (const char *)&pkt_info[IPTRACE_1_0_PKT_TEXT_OFFSET]);
578 /* Get the packet data */
579 if (!iptrace_read_rec_data(fh, buf, rec, err, err_info))
580 return false;
583 * No errors - get the interface ID.
585 * We do *not* trust the name to be null-terminated.
587 memcpy(info.prefix, &pkt_info[IPTRACE_2_0_PREFIX_OFFSET],
588 sizeof info.prefix);
589 info.prefix[PREFIX_SIZE] = '\0';
590 info.unit = pkt_info[IPTRACE_2_0_UNIT_OFFSET];
593 * Try to find the entry with that name, description, and
594 * interface type.
596 if (!g_hash_table_lookup_extended(iptrace->interface_ids,
597 (gconstpointer)&info, NULL, &result)) {
598 wtap_block_t int_data;
599 wtapng_if_descr_mandatory_t *int_data_mand;
602 * Not found; make a new entry.
604 add_new_if_info(iptrace, &info, &result);
607 * Now make a new IDB and add it.
609 int_data = wtap_block_create(WTAP_BLOCK_IF_ID_AND_INFO);
610 int_data_mand = (wtapng_if_descr_mandatory_t *)wtap_block_get_mandatory_data(int_data);
612 int_data_mand->wtap_encap = rec->rec_header.packet_header.pkt_encap;
613 int_data_mand->tsprecision = WTAP_TSPREC_NSEC;
614 int_data_mand->time_units_per_second = 1000000000; /* Nanosecond resolution */
615 int_data_mand->snap_len = WTAP_MAX_PACKET_SIZE_STANDARD; /* XXX - not known */
617 wtap_block_add_uint8_option(int_data, OPT_IDB_TSRESOL, 0x09); /* nanosecond resolution */
618 /* Interface statistics */
619 int_data_mand->num_stat_entries = 0;
620 int_data_mand->interface_statistics = NULL;
622 wtap_block_set_string_option_value_format(int_data,
623 OPT_IDB_NAME, "%s%u", info.prefix, info.unit);
624 wtap_add_idb(wth, int_data);
626 rec->rec_header.packet_header.interface_id = GPOINTER_TO_UINT(result);
627 return true;
630 /* Read the next packet */
631 static bool iptrace_read_2_0(wtap *wth, wtap_rec *rec,
632 Buffer *buf, int *err, char **err_info, int64_t *data_offset)
634 *data_offset = file_tell(wth->fh);
636 /* Read the packet */
637 if (!iptrace_read_rec_2_0(wth, wth->fh, rec, buf, err, err_info)) {
638 /* Read error or EOF */
639 return false;
642 /* If the per-file encapsulation isn't known, set it to this
643 packet's encapsulation.
645 If it *is* known, and it isn't this packet's encapsulation,
646 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
647 have a single encapsulation for all packets in the file. */
648 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
649 wth->file_encap = rec->rec_header.packet_header.pkt_encap;
650 else {
651 if (wth->file_encap != rec->rec_header.packet_header.pkt_encap)
652 wth->file_encap = WTAP_ENCAP_PER_PACKET;
655 return true;
658 static bool iptrace_seek_read_2_0(wtap *wth, int64_t seek_off,
659 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
661 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
662 return false;
664 /* Read the packet */
665 if (!iptrace_read_rec_2_0(wth, wth->random_fh, rec, buf, err,
666 err_info)) {
667 if (*err == 0)
668 *err = WTAP_ERR_SHORT_READ;
669 return false;
671 return true;
674 static bool
675 iptrace_read_rec_data(FILE_T fh, Buffer *buf, wtap_rec *rec,
676 int *err, char **err_info)
678 if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
679 return false;
681 if (rec->rec_header.packet_header.pkt_encap == WTAP_ENCAP_ATM_PDUS) {
683 * Attempt to guess from the packet data, the VPI,
684 * and the VCI information about the type of traffic.
686 atm_guess_traffic_type(rec, ws_buffer_start_ptr(buf));
689 return true;
693 * Fill in the pseudo-header information we can.
695 * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic
696 * is in the packet - it was presumably run on a machine that was one of
697 * the endpoints of the connection, so in theory it could presumably have
698 * told us, but, for whatever reason, it failed to do so - perhaps the
699 * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't
700 * have access to that information (e.g., because it's in the ATM driver,
701 * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be
702 * handed up to some particular client, it doesn't know what that client is).
704 * We let our caller try to figure out what kind of traffic it is, either
705 * by guessing based on the VPI/VCI, guessing based on the header of the
706 * packet, seeing earlier traffic that set up the circuit and specified
707 * in some fashion what sort of traffic it is, or being told by the user.
709 static void
710 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
711 const char *pkt_text)
713 char if_text[9];
714 char *decimal;
715 int Vpi = 0;
716 int Vci = 0;
718 switch (encap) {
720 case WTAP_ENCAP_ATM_PDUS:
721 /* Rip apart the "x.y" text into Vpi/Vci numbers */
722 memcpy(if_text, &pkt_text[4], 8);
723 if_text[8] = '\0';
724 decimal = strchr(if_text, '.');
725 if (decimal) {
726 *decimal = '\0';
727 Vpi = (int)strtoul(if_text, NULL, 10);
728 decimal++;
729 Vci = (int)strtoul(decimal, NULL, 10);
733 * OK, which value means "DTE->DCE" and which value means
734 * "DCE->DTE"?
736 pseudo_header->atm.channel = pkt_text[13];
738 pseudo_header->atm.vpi = Vpi;
739 pseudo_header->atm.vci = Vci;
741 /* We don't have this information */
742 pseudo_header->atm.flags = 0;
743 pseudo_header->atm.cells = 0;
744 pseudo_header->atm.aal5t_u2u = 0;
745 pseudo_header->atm.aal5t_len = 0;
746 pseudo_header->atm.aal5t_chksum = 0;
747 break;
749 case WTAP_ENCAP_ETHERNET:
750 /* We assume there's no FCS in this frame. */
751 pseudo_header->eth.fcs_len = 0;
752 break;
756 /* Given an RFC1573 (SNMP ifType) interface type,
757 * return the appropriate Wiretap Encapsulation Type.
759 static int
760 wtap_encap_ift(unsigned int ift)
763 static const int ift_encap[] = {
764 /* 0x0 */ WTAP_ENCAP_UNKNOWN, /* nothing */
765 /* 0x1 */ WTAP_ENCAP_UNKNOWN, /* IFT_OTHER */
766 /* 0x2 */ WTAP_ENCAP_UNKNOWN, /* IFT_1822 */
767 /* 0x3 */ WTAP_ENCAP_UNKNOWN, /* IFT_HDH1822 */
768 /* 0x4 */ WTAP_ENCAP_RAW_IP, /* IFT_X25DDN */
769 /* 0x5 */ WTAP_ENCAP_UNKNOWN, /* IFT_X25 */
770 /* 0x6 */ WTAP_ENCAP_ETHERNET, /* IFT_ETHER */
771 /* 0x7 */ WTAP_ENCAP_ETHERNET, /* IFT_ISO88023 */
772 /* 0x8 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88024 */
773 /* 0x9 */ WTAP_ENCAP_TOKEN_RING, /* IFT_ISO88025 */
774 /* 0xa */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88026 */
775 /* 0xb */ WTAP_ENCAP_UNKNOWN, /* IFT_STARLAN */
776 /* 0xc */ WTAP_ENCAP_RAW_IP, /* IFT_P10, IBM SP switch */
777 /* 0xd */ WTAP_ENCAP_UNKNOWN, /* IFT_P80 */
778 /* 0xe */ WTAP_ENCAP_UNKNOWN, /* IFT_HY */
779 /* 0xf */ WTAP_ENCAP_FDDI_BITSWAPPED, /* IFT_FDDI */
780 /* 0x10 */ WTAP_ENCAP_LAPB, /* IFT_LAPB */ /* no data to back this up */
781 /* 0x11 */ WTAP_ENCAP_UNKNOWN, /* IFT_SDLC */
782 /* 0x12 */ WTAP_ENCAP_UNKNOWN, /* IFT_T1 */
783 /* 0x13 */ WTAP_ENCAP_UNKNOWN, /* IFT_CEPT */
784 /* 0x14 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNBASIC */
785 /* 0x15 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNPRIMARY */
786 /* 0x16 */ WTAP_ENCAP_UNKNOWN, /* IFT_PTPSERIAL */
787 /* 0x17 */ WTAP_ENCAP_UNKNOWN, /* IFT_PPP */
788 /* 0x18 */ WTAP_ENCAP_RAW_IP, /* IFT_LOOP */
789 /* 0x19 */ WTAP_ENCAP_UNKNOWN, /* IFT_EON */
790 /* 0x1a */ WTAP_ENCAP_UNKNOWN, /* IFT_XETHER */
791 /* 0x1b */ WTAP_ENCAP_UNKNOWN, /* IFT_NSIP */
792 /* 0x1c */ WTAP_ENCAP_UNKNOWN, /* IFT_SLIP */
793 /* 0x1d */ WTAP_ENCAP_UNKNOWN, /* IFT_ULTRA */
794 /* 0x1e */ WTAP_ENCAP_UNKNOWN, /* IFT_DS3 */
795 /* 0x1f */ WTAP_ENCAP_UNKNOWN, /* IFT_SIP */
796 /* 0x20 */ WTAP_ENCAP_UNKNOWN, /* IFT_FRELAY */
797 /* 0x21 */ WTAP_ENCAP_UNKNOWN, /* IFT_RS232 */
798 /* 0x22 */ WTAP_ENCAP_UNKNOWN, /* IFT_PARA */
799 /* 0x23 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNET */
800 /* 0x24 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNETPLUS */
801 /* 0x25 */ WTAP_ENCAP_ATM_PDUS, /* IFT_ATM */
803 #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])
805 if (ift < NUM_IFT_ENCAPS) {
806 return ift_encap[ift];
808 else {
809 switch(ift) {
810 /* Infiniband*/
811 case IPTRACE_IFT_IB:
812 return WTAP_ENCAP_INFINIBAND;
813 break;
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;
827 break;
829 default:
830 return WTAP_ENCAP_UNKNOWN;
835 /* Options for interface blocks. */
836 static const struct supported_option_type interface_block_options_supported[] = {
837 /* No comments, just an interface name. */
838 { OPT_IDB_NAME, ONE_OPTION_SUPPORTED }
841 static const struct supported_block_type iptrace_1_0_blocks_supported[] = {
843 * iptrace supports multiple interfaces, with descriptions, and
844 * supports associating packets with interfaces. Interface
845 * description blocks are used for that.
847 { WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
850 * iptrace is a capture format, so it obviously supports packets.
851 * It supports no packet options, however.
853 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
856 static const struct file_type_subtype_info iptrace_1_0_info = {
857 "AIX iptrace 1.0", "iptrace_1", NULL, NULL,
858 false, BLOCKS_SUPPORTED(iptrace_1_0_blocks_supported),
859 NULL, NULL, NULL
862 static const struct supported_block_type iptrace_2_0_blocks_supported[] = {
864 * iptrace supports multiple interfaces, with descriptions, and
865 * supports associating packets with interfaces. Interface
866 * description blocks are used for that.
868 { WTAP_BLOCK_IF_ID_AND_INFO, MULTIPLE_BLOCKS_SUPPORTED, OPTION_TYPES_SUPPORTED(interface_block_options_supported) },
871 * iptrace is a capture format, so it obviously supports packets.
872 * It supports no packet options, however.
874 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
877 static const struct file_type_subtype_info iptrace_2_0_info = {
878 "AIX iptrace 2.0", "iptrace_2", NULL, NULL,
879 false, BLOCKS_SUPPORTED(iptrace_2_0_blocks_supported),
880 NULL, NULL, NULL
883 void register_iptrace(void)
885 iptrace_1_0_file_type_subtype = wtap_register_file_type_subtype(&iptrace_1_0_info);
886 iptrace_2_0_file_type_subtype = wtap_register_file_type_subtype(&iptrace_2_0_info);
889 * Register names for backwards compatibility with the
890 * wtap_filetypes table in Lua.
892 wtap_register_backwards_compatibility_lua_name("IPTRACE_1_0",
893 iptrace_1_0_file_type_subtype);
894 wtap_register_backwards_compatibility_lua_name("IPTRACE_2_0",
895 iptrace_2_0_file_type_subtype);
899 * Editor modelines - https://www.wireshark.org/tools/modelines.html
901 * Local variables:
902 * c-basic-offset: 8
903 * tab-width: 8
904 * indent-tabs-mode: t
905 * End:
907 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
908 * :indentSize=8:tabSize=8:noTabs=false: