4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "file_wrappers.h"
31 #define IPTRACE_IFT_HF 0x3d /* Support for PERCS IP-HFI*/
32 #define IPTRACE_IFT_IB 0xc7 /* IP over Infiniband. Number by IANA */
34 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
36 static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
37 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
39 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
41 static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
42 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
44 static int iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len,
45 int *err, gchar **err_info);
46 static gboolean iptrace_read_rec_data(FILE_T fh, Buffer *buf,
47 struct wtap_pkthdr *phdr, int *err, gchar **err_info);
48 static void fill_in_pseudo_header(int encap,
49 union wtap_pseudo_header *pseudo_header, guint8 *header);
50 static int wtap_encap_ift(unsigned int ift);
52 int iptrace_open(wtap *wth, int *err, gchar **err_info)
57 errno = WTAP_ERR_CANT_READ;
58 bytes_read = file_read(name, 11, wth->fh);
59 if (bytes_read != 11) {
60 *err = file_error(wth->fh, err_info);
61 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
67 if (strcmp(name, "iptrace 1.0") == 0) {
68 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0;
69 wth->subtype_read = iptrace_read_1_0;
70 wth->subtype_seek_read = iptrace_seek_read_1_0;
71 wth->tsprecision = WTAP_FILE_TSPREC_SEC;
73 else if (strcmp(name, "iptrace 2.0") == 0) {
74 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0;
75 wth->subtype_read = iptrace_read_2_0;
76 wth->subtype_seek_read = iptrace_seek_read_2_0;
77 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
86 /***********************************************************
88 ***********************************************************/
91 * iptrace 1.0, discovered through inspection
93 * Packet record contains:
95 * an initial header, with a length field and a time stamp, in
96 * seconds since the Epoch;
98 * data, with the specified length.
102 * a bunch of information about the packet;
104 * padding, at least for FDDI;
106 * the raw packet data.
109 /* 0-3 */ guint32 pkt_length; /* packet length + 0x16 */
110 /* 4-7 */ guint32 tv_sec; /* time stamp, seconds since the Epoch */
111 /* 8-11 */ guint32 junk1; /* ???, not time */
112 /* 12-15 */ char if_name[4]; /* null-terminated */
113 /* 16-27 */ char junk2[12]; /* ??? */
114 /* 28 */ guint8 if_type; /* BSD net/if_types.h */
115 /* 29 */ guint8 tx_flag; /* 0=receive, 1=transmit */
118 #define IPTRACE_1_0_PHDR_SIZE 30 /* initial header plus packet data */
119 #define IPTRACE_1_0_PDATA_SIZE 22 /* packet data */
122 iptrace_read_rec_1_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
123 int *err, gchar **err_info)
125 guint8 header[IPTRACE_1_0_PHDR_SIZE];
127 iptrace_1_0_phdr pkt_hdr;
130 ret = iptrace_read_rec_header(fh, header, IPTRACE_1_0_PHDR_SIZE,
133 /* Read error or EOF */
138 * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
139 * value giving the type of the interface. Check out the
140 * <net/if_types.h> header file.
142 pkt_hdr.if_type = header[28];
143 phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
144 if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
145 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
146 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
151 /* Read the packet metadata */
152 packet_size = pntoh32(&header[0]);
153 if (packet_size < IPTRACE_1_0_PDATA_SIZE) {
155 * Uh-oh, the record isn't big enough to even have a
156 * packet meta-data header.
158 *err = WTAP_ERR_BAD_FILE;
159 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
163 packet_size -= IPTRACE_1_0_PDATA_SIZE;
166 * AIX appears to put 3 bytes of padding in front of FDDI
167 * frames; strip that crap off.
169 if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
171 * The packet size is really a record size and includes
174 if (packet_size < 3) {
176 * Uh-oh, the record isn't big enough to even have
179 *err = WTAP_ERR_BAD_FILE;
180 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
181 packet_size + IPTRACE_1_0_PDATA_SIZE);
189 if (!file_skip(fh, 3, err))
192 if (packet_size > WTAP_MAX_PACKET_SIZE) {
194 * Probably a corrupt capture file; don't blow up trying
195 * to allocate space for an immensely-large packet.
197 *err = WTAP_ERR_BAD_FILE;
198 *err_info = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
199 packet_size, WTAP_MAX_PACKET_SIZE);
203 phdr->presence_flags = WTAP_HAS_TS;
204 phdr->len = packet_size;
205 phdr->caplen = packet_size;
206 phdr->ts.secs = pntoh32(&header[4]);
209 /* Fill in the pseudo-header. */
210 fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
212 /* Get the packet data */
213 return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
216 /* Read the next packet */
217 static int iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
220 *data_offset = file_tell(wth->fh);
222 /* Read the packet */
223 if (!iptrace_read_rec_1_0(wth->fh, &wth->phdr, wth->frame_buffer,
225 /* Read error or EOF */
229 /* If the per-file encapsulation isn't known, set it to this
230 packet's encapsulation.
232 If it *is* known, and it isn't this packet's encapsulation,
233 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
234 have a single encapsulation for all packets in the file. */
235 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
236 wth->file_encap = wth->phdr.pkt_encap;
238 if (wth->file_encap != wth->phdr.pkt_encap)
239 wth->file_encap = WTAP_ENCAP_PER_PACKET;
242 return REC_TYPE_PACKET;
245 static int iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
246 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
248 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
251 /* Read the packet */
252 if (!iptrace_read_rec_1_0(wth->random_fh, phdr, buf, err, err_info)) {
254 *err = WTAP_ERR_SHORT_READ;
257 return REC_TYPE_PACKET;
260 /***********************************************************
262 ***********************************************************/
265 * iptrace 2.0, discovered through inspection
267 * Packet record contains:
269 * an initial header, with a length field and a time stamp, in
270 * seconds since the Epoch;
272 * data, with the specified length.
276 * a bunch of information about the packet;
278 * padding, at least for FDDI;
280 * the raw packet data.
283 /* 0-3 */ guint32 pkt_length; /* packet length + 32 */
284 /* 4-7 */ guint32 tv_sec0; /* time stamp, seconds since the Epoch */
285 /* 8-11 */ guint32 junk1; /* ?? */
286 /* 12-15 */ char if_name[4]; /* null-terminated */
287 /* 16-27 */ char if_desc[12]; /* interface description. */
288 /* 28 */ guint8 if_type; /* BSD net/if_types.h */
289 /* 29 */ guint8 tx_flag; /* 0=receive, 1=transmit */
290 /* 30-31 */ guint16 junk3;
291 /* 32-35 */ guint32 tv_sec; /* time stamp, seconds since the Epoch */
292 /* 36-39 */ guint32 tv_nsec; /* nanoseconds since that second */
295 #define IPTRACE_2_0_PHDR_SIZE 40 /* initial header plus packet data */
296 #define IPTRACE_2_0_PDATA_SIZE 32 /* packet data */
299 iptrace_read_rec_2_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
300 int *err, gchar **err_info)
302 guint8 header[IPTRACE_2_0_PHDR_SIZE];
304 iptrace_2_0_phdr pkt_hdr;
307 ret = iptrace_read_rec_header(fh, header, IPTRACE_2_0_PHDR_SIZE,
310 /* Read error or EOF */
315 * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
316 * value giving the type of the interface. Check out the
317 * <net/if_types.h> header file.
319 pkt_hdr.if_type = header[28];
320 phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
323 * We used to error out if the interface type in iptrace was
324 * unknown/unhandled, but an iptrace may contain packets
325 * from a variety of interfaces, some known, and others
328 * It is better to display the data even for unknown interface
329 * types, isntead of erroring out. In the future, it would be
330 * nice to be able to flag which frames are shown as data
331 * because their interface type is unknown, and also present
332 * the interface type number to the user so that it can be
333 * reported easily back to the Wireshark developer.
335 * XXX - what types are there that are used in files but
336 * that we don't handle?
338 if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
339 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
340 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
346 /* Read the packet metadata */
347 packet_size = pntoh32(&header[0]);
348 if (packet_size < IPTRACE_2_0_PDATA_SIZE) {
350 * Uh-oh, the record isn't big enough to even have a
351 * packet meta-data header.
353 *err = WTAP_ERR_BAD_FILE;
354 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
358 packet_size -= IPTRACE_2_0_PDATA_SIZE;
361 * AIX appears to put 3 bytes of padding in front of FDDI
362 * frames; strip that crap off.
364 if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
366 * The packet size is really a record size and includes
369 if (packet_size < 3) {
371 * Uh-oh, the record isn't big enough to even have
374 *err = WTAP_ERR_BAD_FILE;
375 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
376 packet_size + IPTRACE_2_0_PDATA_SIZE);
384 if (!file_skip(fh, 3, err))
387 if (packet_size > WTAP_MAX_PACKET_SIZE) {
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 = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
394 packet_size, WTAP_MAX_PACKET_SIZE);
398 phdr->presence_flags = WTAP_HAS_TS;
399 phdr->len = packet_size;
400 phdr->caplen = packet_size;
401 phdr->ts.secs = pntoh32(&header[32]);
402 phdr->ts.nsecs = pntoh32(&header[36]);
404 /* Fill in the pseudo_header. */
405 fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
407 /* Get the packet data */
408 return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
411 /* Read the next packet */
412 static int iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
415 *data_offset = file_tell(wth->fh);
417 /* Read the packet */
418 if (!iptrace_read_rec_2_0(wth->fh, &wth->phdr, wth->frame_buffer,
420 /* Read error or EOF */
424 /* If the per-file encapsulation isn't known, set it to this
425 packet's encapsulation.
427 If it *is* known, and it isn't this packet's encapsulation,
428 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
429 have a single encapsulation for all packets in the file. */
430 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
431 wth->file_encap = wth->phdr.pkt_encap;
433 if (wth->file_encap != wth->phdr.pkt_encap)
434 wth->file_encap = WTAP_ENCAP_PER_PACKET;
437 return REC_TYPE_PACKET;
440 static int iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
441 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
443 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
446 /* Read the packet */
447 if (!iptrace_read_rec_2_0(wth->random_fh, phdr, buf, err, err_info)) {
449 *err = WTAP_ERR_SHORT_READ;
452 return REC_TYPE_PACKET;
456 iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len, int *err,
461 errno = WTAP_ERR_CANT_READ;
462 bytes_read = file_read(header, header_len, fh);
463 if (bytes_read != header_len) {
464 *err = file_error(fh, err_info);
467 if (bytes_read != 0) {
468 *err = WTAP_ERR_SHORT_READ;
477 iptrace_read_rec_data(FILE_T fh, Buffer *buf, struct wtap_pkthdr *phdr,
478 int *err, gchar **err_info)
480 if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
483 if (phdr->pkt_encap == WTAP_ENCAP_ATM_PDUS) {
485 * Attempt to guess from the packet data, the VPI,
486 * and the VCI information about the type of traffic.
488 atm_guess_traffic_type(phdr, buffer_start_ptr(buf));
495 * Fill in the pseudo-header information we can.
497 * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic
498 * is in the packet - it was presumably run on a machine that was one of
499 * the endpoints of the connection, so in theory it could presumably have
500 * told us, but, for whatever reason, it failed to do so - perhaps the
501 * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't
502 * have access to that information (e.g., because it's in the ATM driver,
503 * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be
504 * handed up to some particular client, it doesn't know what that client is).
506 * We let our caller try to figure out what kind of traffic it is, either
507 * by guessing based on the VPI/VCI, guessing based on the header of the
508 * packet, seeing earlier traffic that set up the circuit and specified
509 * in some fashion what sort of traffic it is, or being told by the user.
512 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
522 case WTAP_ENCAP_ATM_PDUS:
523 /* Rip apart the "x.y" text into Vpi/Vci numbers */
524 memcpy(if_text, &header[20], 8);
526 decimal = strchr(if_text, '.');
529 Vpi = (int)strtoul(if_text, NULL, 10);
531 Vci = (int)strtoul(decimal, NULL, 10);
535 * OK, which value means "DTE->DCE" and which value means
538 pseudo_header->atm.channel = header[29];
540 pseudo_header->atm.vpi = Vpi;
541 pseudo_header->atm.vci = Vci;
543 /* We don't have this information */
544 pseudo_header->atm.flags = 0;
545 pseudo_header->atm.cells = 0;
546 pseudo_header->atm.aal5t_u2u = 0;
547 pseudo_header->atm.aal5t_len = 0;
548 pseudo_header->atm.aal5t_chksum = 0;
551 case WTAP_ENCAP_ETHERNET:
552 /* We assume there's no FCS in this frame. */
553 pseudo_header->eth.fcs_len = 0;
558 /* Given an RFC1573 (SNMP ifType) interface type,
559 * return the appropriate Wiretap Encapsulation Type.
562 wtap_encap_ift(unsigned int ift)
565 static const int ift_encap[] = {
566 /* 0x0 */ WTAP_ENCAP_UNKNOWN, /* nothing */
567 /* 0x1 */ WTAP_ENCAP_UNKNOWN, /* IFT_OTHER */
568 /* 0x2 */ WTAP_ENCAP_UNKNOWN, /* IFT_1822 */
569 /* 0x3 */ WTAP_ENCAP_UNKNOWN, /* IFT_HDH1822 */
570 /* 0x4 */ WTAP_ENCAP_RAW_IP, /* IFT_X25DDN */
571 /* 0x5 */ WTAP_ENCAP_UNKNOWN, /* IFT_X25 */
572 /* 0x6 */ WTAP_ENCAP_ETHERNET, /* IFT_ETHER */
573 /* 0x7 */ WTAP_ENCAP_ETHERNET, /* IFT_ISO88023 */
574 /* 0x8 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88024 */
575 /* 0x9 */ WTAP_ENCAP_TOKEN_RING, /* IFT_ISO88025 */
576 /* 0xa */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88026 */
577 /* 0xb */ WTAP_ENCAP_UNKNOWN, /* IFT_STARLAN */
578 /* 0xc */ WTAP_ENCAP_RAW_IP, /* IFT_P10, IBM SP switch */
579 /* 0xd */ WTAP_ENCAP_UNKNOWN, /* IFT_P80 */
580 /* 0xe */ WTAP_ENCAP_UNKNOWN, /* IFT_HY */
581 /* 0xf */ WTAP_ENCAP_FDDI_BITSWAPPED, /* IFT_FDDI */
582 /* 0x10 */ WTAP_ENCAP_LAPB, /* IFT_LAPB */ /* no data to back this up */
583 /* 0x11 */ WTAP_ENCAP_UNKNOWN, /* IFT_SDLC */
584 /* 0x12 */ WTAP_ENCAP_UNKNOWN, /* IFT_T1 */
585 /* 0x13 */ WTAP_ENCAP_UNKNOWN, /* IFT_CEPT */
586 /* 0x14 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNBASIC */
587 /* 0x15 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNPRIMARY */
588 /* 0x16 */ WTAP_ENCAP_UNKNOWN, /* IFT_PTPSERIAL */
589 /* 0x17 */ WTAP_ENCAP_UNKNOWN, /* IFT_PPP */
590 /* 0x18 */ WTAP_ENCAP_RAW_IP, /* IFT_LOOP */
591 /* 0x19 */ WTAP_ENCAP_UNKNOWN, /* IFT_EON */
592 /* 0x1a */ WTAP_ENCAP_UNKNOWN, /* IFT_XETHER */
593 /* 0x1b */ WTAP_ENCAP_UNKNOWN, /* IFT_NSIP */
594 /* 0x1c */ WTAP_ENCAP_UNKNOWN, /* IFT_SLIP */
595 /* 0x1d */ WTAP_ENCAP_UNKNOWN, /* IFT_ULTRA */
596 /* 0x1e */ WTAP_ENCAP_UNKNOWN, /* IFT_DS3 */
597 /* 0x1f */ WTAP_ENCAP_UNKNOWN, /* IFT_SIP */
598 /* 0x20 */ WTAP_ENCAP_UNKNOWN, /* IFT_FRELAY */
599 /* 0x21 */ WTAP_ENCAP_UNKNOWN, /* IFT_RS232 */
600 /* 0x22 */ WTAP_ENCAP_UNKNOWN, /* IFT_PARA */
601 /* 0x23 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNET */
602 /* 0x24 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNETPLUS */
603 /* 0x25 */ WTAP_ENCAP_ATM_PDUS, /* IFT_ATM */
605 #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])
607 if (ift < NUM_IFT_ENCAPS) {
608 return ift_encap[ift];
614 return WTAP_ENCAP_INFINIBAND;
617 /* Host Fabric Interface */
619 /* The HFI interface on AIX provides raw IP
620 in the packet trace. It's unclear if the HFI
621 can be configured for any other protocol, and if
622 any field in the iptrace header indicates what
623 that protocol is. For now, we are hard-coding
624 this as RAW_IP, but if we find another iptrace file
625 using HFI that provides another protocol, we will
626 have to figure out which field in the iptrace file
628 return WTAP_ENCAP_RAW_IP;
632 return WTAP_ENCAP_UNKNOWN;