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"
30 #define IPTRACE_IFT_HF 0x3d /* Support for PERCS IP-HFI*/
31 #define IPTRACE_IFT_IB 0xc7 /* IP over Infiniband. Number by IANA */
33 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
35 static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
36 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
38 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
40 static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
41 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
43 static gboolean iptrace_read_rec_data(FILE_T fh, Buffer *buf,
44 struct wtap_pkthdr *phdr, int *err, gchar **err_info);
45 static void fill_in_pseudo_header(int encap,
46 union wtap_pseudo_header *pseudo_header, guint8 *header);
47 static int wtap_encap_ift(unsigned int ift);
51 wtap_open_return_val iptrace_open(wtap *wth, int *err, gchar **err_info)
53 char name[NAME_SIZE+1];
55 if (!wtap_read_bytes(wth->fh, name, NAME_SIZE, err, err_info)) {
56 if (*err != WTAP_ERR_SHORT_READ)
57 return WTAP_OPEN_ERROR;
58 return WTAP_OPEN_NOT_MINE;
60 name[NAME_SIZE] = '\0';
62 if (strcmp(name, "iptrace 1.0") == 0) {
63 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0;
64 wth->subtype_read = iptrace_read_1_0;
65 wth->subtype_seek_read = iptrace_seek_read_1_0;
66 wth->file_tsprec = WTAP_TSPREC_SEC;
68 else if (strcmp(name, "iptrace 2.0") == 0) {
69 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0;
70 wth->subtype_read = iptrace_read_2_0;
71 wth->subtype_seek_read = iptrace_seek_read_2_0;
72 wth->file_tsprec = WTAP_TSPREC_NSEC;
75 return WTAP_OPEN_NOT_MINE;
78 return WTAP_OPEN_MINE;
81 /***********************************************************
83 ***********************************************************/
86 * iptrace 1.0, discovered through inspection
88 * Packet record contains:
90 * an initial header, with a length field and a time stamp, in
91 * seconds since the Epoch;
93 * data, with the specified length.
97 * a bunch of information about the packet;
99 * padding, at least for FDDI;
101 * the raw packet data.
104 /* 0-3 */ guint32 pkt_length; /* packet length + 0x16 */
105 /* 4-7 */ guint32 tv_sec; /* time stamp, seconds since the Epoch */
106 /* 8-11 */ guint32 junk1; /* ???, not time */
107 /* 12-15 */ char if_name[4]; /* null-terminated */
108 /* 16-27 */ char junk2[12]; /* ??? */
109 /* 28 */ guint8 if_type; /* BSD net/if_types.h */
110 /* 29 */ guint8 tx_flag; /* 0=receive, 1=transmit */
113 #define IPTRACE_1_0_PHDR_SIZE 30 /* initial header plus packet data */
114 #define IPTRACE_1_0_PDATA_SIZE 22 /* packet data */
117 iptrace_read_rec_1_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
118 int *err, gchar **err_info)
120 guint8 header[IPTRACE_1_0_PHDR_SIZE];
121 iptrace_1_0_phdr pkt_hdr;
124 if (!wtap_read_bytes_or_eof(fh, header, sizeof header, err, err_info)) {
125 /* Read error or EOF */
130 * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
131 * value giving the type of the interface. Check out the
132 * <net/if_types.h> header file.
134 pkt_hdr.if_type = header[28];
135 phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
136 if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
137 *err = WTAP_ERR_UNSUPPORTED;
138 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
143 /* Read the packet metadata */
144 packet_size = pntoh32(&header[0]);
145 if (packet_size < IPTRACE_1_0_PDATA_SIZE) {
147 * Uh-oh, the record isn't big enough to even have a
148 * packet meta-data header.
150 *err = WTAP_ERR_BAD_FILE;
151 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
155 packet_size -= IPTRACE_1_0_PDATA_SIZE;
158 * AIX appears to put 3 bytes of padding in front of FDDI
159 * frames; strip that crap off.
161 if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
163 * The packet size is really a record size and includes
166 if (packet_size < 3) {
168 * Uh-oh, the record isn't big enough to even have
171 *err = WTAP_ERR_BAD_FILE;
172 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
173 packet_size + IPTRACE_1_0_PDATA_SIZE);
181 if (!file_skip(fh, 3, err))
184 if (packet_size > WTAP_MAX_PACKET_SIZE) {
186 * Probably a corrupt capture file; don't blow up trying
187 * to allocate space for an immensely-large packet.
189 *err = WTAP_ERR_BAD_FILE;
190 *err_info = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
191 packet_size, WTAP_MAX_PACKET_SIZE);
195 phdr->rec_type = REC_TYPE_PACKET;
196 phdr->presence_flags = WTAP_HAS_TS;
197 phdr->len = packet_size;
198 phdr->caplen = packet_size;
199 phdr->ts.secs = pntoh32(&header[4]);
202 /* Fill in the pseudo-header. */
203 fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
205 /* Get the packet data */
206 return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
209 /* Read the next packet */
210 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
213 *data_offset = file_tell(wth->fh);
215 /* Read the packet */
216 if (!iptrace_read_rec_1_0(wth->fh, &wth->phdr, wth->frame_buffer,
218 /* Read error or EOF */
222 /* If the per-file encapsulation isn't known, set it to this
223 packet's encapsulation.
225 If it *is* known, and it isn't this packet's encapsulation,
226 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
227 have a single encapsulation for all packets in the file. */
228 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
229 wth->file_encap = wth->phdr.pkt_encap;
231 if (wth->file_encap != wth->phdr.pkt_encap)
232 wth->file_encap = WTAP_ENCAP_PER_PACKET;
238 static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
239 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
241 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
244 /* Read the packet */
245 if (!iptrace_read_rec_1_0(wth->random_fh, phdr, buf, err, err_info)) {
247 *err = WTAP_ERR_SHORT_READ;
253 /***********************************************************
255 ***********************************************************/
258 * iptrace 2.0, discovered through inspection
260 * Packet record contains:
262 * an initial header, with a length field and a time stamp, in
263 * seconds since the Epoch;
265 * data, with the specified length.
269 * a bunch of information about the packet;
271 * padding, at least for FDDI;
273 * the raw packet data.
276 /* 0-3 */ guint32 pkt_length; /* packet length + 32 */
277 /* 4-7 */ guint32 tv_sec0; /* time stamp, seconds since the Epoch */
278 /* 8-11 */ guint32 junk1; /* ?? */
279 /* 12-15 */ char if_name[4]; /* null-terminated */
280 /* 16-27 */ char if_desc[12]; /* interface description. */
281 /* 28 */ guint8 if_type; /* BSD net/if_types.h */
282 /* 29 */ guint8 tx_flag; /* 0=receive, 1=transmit */
283 /* 30-31 */ guint16 junk3;
284 /* 32-35 */ guint32 tv_sec; /* time stamp, seconds since the Epoch */
285 /* 36-39 */ guint32 tv_nsec; /* nanoseconds since that second */
288 #define IPTRACE_2_0_PHDR_SIZE 40 /* initial header plus packet data */
289 #define IPTRACE_2_0_PDATA_SIZE 32 /* packet data */
292 iptrace_read_rec_2_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
293 int *err, gchar **err_info)
295 guint8 header[IPTRACE_2_0_PHDR_SIZE];
296 iptrace_2_0_phdr pkt_hdr;
299 if (!wtap_read_bytes_or_eof(fh, header, sizeof header, err, err_info)) {
300 /* Read error or EOF */
305 * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
306 * value giving the type of the interface. Check out the
307 * <net/if_types.h> header file.
309 pkt_hdr.if_type = header[28];
310 phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
313 * We used to error out if the interface type in iptrace was
314 * unknown/unhandled, but an iptrace may contain packets
315 * from a variety of interfaces, some known, and others
318 * It is better to display the data even for unknown interface
319 * types, isntead of erroring out. In the future, it would be
320 * nice to be able to flag which frames are shown as data
321 * because their interface type is unknown, and also present
322 * the interface type number to the user so that it can be
323 * reported easily back to the Wireshark developer.
325 * XXX - what types are there that are used in files but
326 * that we don't handle?
328 if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
329 *err = WTAP_ERR_UNSUPPORTED;
330 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
336 /* Read the packet metadata */
337 packet_size = pntoh32(&header[0]);
338 if (packet_size < IPTRACE_2_0_PDATA_SIZE) {
340 * Uh-oh, the record isn't big enough to even have a
341 * packet meta-data header.
343 *err = WTAP_ERR_BAD_FILE;
344 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
348 packet_size -= IPTRACE_2_0_PDATA_SIZE;
351 * AIX appears to put 3 bytes of padding in front of FDDI
352 * frames; strip that crap off.
354 if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
356 * The packet size is really a record size and includes
359 if (packet_size < 3) {
361 * Uh-oh, the record isn't big enough to even have
364 *err = WTAP_ERR_BAD_FILE;
365 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
366 packet_size + IPTRACE_2_0_PDATA_SIZE);
374 if (!file_skip(fh, 3, err))
377 if (packet_size > WTAP_MAX_PACKET_SIZE) {
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 = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
384 packet_size, WTAP_MAX_PACKET_SIZE);
388 phdr->rec_type = REC_TYPE_PACKET;
389 phdr->presence_flags = WTAP_HAS_TS;
390 phdr->len = packet_size;
391 phdr->caplen = packet_size;
392 phdr->ts.secs = pntoh32(&header[32]);
393 phdr->ts.nsecs = pntoh32(&header[36]);
395 /* Fill in the pseudo_header. */
396 fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
398 /* Get the packet data */
399 return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
402 /* Read the next packet */
403 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
406 *data_offset = file_tell(wth->fh);
408 /* Read the packet */
409 if (!iptrace_read_rec_2_0(wth->fh, &wth->phdr, wth->frame_buffer,
411 /* Read error or EOF */
415 /* If the per-file encapsulation isn't known, set it to this
416 packet's encapsulation.
418 If it *is* known, and it isn't this packet's encapsulation,
419 set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
420 have a single encapsulation for all packets in the file. */
421 if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
422 wth->file_encap = wth->phdr.pkt_encap;
424 if (wth->file_encap != wth->phdr.pkt_encap)
425 wth->file_encap = WTAP_ENCAP_PER_PACKET;
431 static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
432 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
434 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
437 /* Read the packet */
438 if (!iptrace_read_rec_2_0(wth->random_fh, phdr, buf, err, err_info)) {
440 *err = WTAP_ERR_SHORT_READ;
447 iptrace_read_rec_data(FILE_T fh, Buffer *buf, struct wtap_pkthdr *phdr,
448 int *err, gchar **err_info)
450 if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
453 if (phdr->pkt_encap == WTAP_ENCAP_ATM_PDUS) {
455 * Attempt to guess from the packet data, the VPI,
456 * and the VCI information about the type of traffic.
458 atm_guess_traffic_type(phdr, ws_buffer_start_ptr(buf));
465 * Fill in the pseudo-header information we can.
467 * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic
468 * is in the packet - it was presumably run on a machine that was one of
469 * the endpoints of the connection, so in theory it could presumably have
470 * told us, but, for whatever reason, it failed to do so - perhaps the
471 * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't
472 * have access to that information (e.g., because it's in the ATM driver,
473 * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be
474 * handed up to some particular client, it doesn't know what that client is).
476 * We let our caller try to figure out what kind of traffic it is, either
477 * by guessing based on the VPI/VCI, guessing based on the header of the
478 * packet, seeing earlier traffic that set up the circuit and specified
479 * in some fashion what sort of traffic it is, or being told by the user.
482 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
492 case WTAP_ENCAP_ATM_PDUS:
493 /* Rip apart the "x.y" text into Vpi/Vci numbers */
494 memcpy(if_text, &header[20], 8);
496 decimal = strchr(if_text, '.');
499 Vpi = (int)strtoul(if_text, NULL, 10);
501 Vci = (int)strtoul(decimal, NULL, 10);
505 * OK, which value means "DTE->DCE" and which value means
508 pseudo_header->atm.channel = header[29];
510 pseudo_header->atm.vpi = Vpi;
511 pseudo_header->atm.vci = Vci;
513 /* We don't have this information */
514 pseudo_header->atm.flags = 0;
515 pseudo_header->atm.cells = 0;
516 pseudo_header->atm.aal5t_u2u = 0;
517 pseudo_header->atm.aal5t_len = 0;
518 pseudo_header->atm.aal5t_chksum = 0;
521 case WTAP_ENCAP_ETHERNET:
522 /* We assume there's no FCS in this frame. */
523 pseudo_header->eth.fcs_len = 0;
528 /* Given an RFC1573 (SNMP ifType) interface type,
529 * return the appropriate Wiretap Encapsulation Type.
532 wtap_encap_ift(unsigned int ift)
535 static const int ift_encap[] = {
536 /* 0x0 */ WTAP_ENCAP_UNKNOWN, /* nothing */
537 /* 0x1 */ WTAP_ENCAP_UNKNOWN, /* IFT_OTHER */
538 /* 0x2 */ WTAP_ENCAP_UNKNOWN, /* IFT_1822 */
539 /* 0x3 */ WTAP_ENCAP_UNKNOWN, /* IFT_HDH1822 */
540 /* 0x4 */ WTAP_ENCAP_RAW_IP, /* IFT_X25DDN */
541 /* 0x5 */ WTAP_ENCAP_UNKNOWN, /* IFT_X25 */
542 /* 0x6 */ WTAP_ENCAP_ETHERNET, /* IFT_ETHER */
543 /* 0x7 */ WTAP_ENCAP_ETHERNET, /* IFT_ISO88023 */
544 /* 0x8 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88024 */
545 /* 0x9 */ WTAP_ENCAP_TOKEN_RING, /* IFT_ISO88025 */
546 /* 0xa */ WTAP_ENCAP_UNKNOWN, /* IFT_ISO88026 */
547 /* 0xb */ WTAP_ENCAP_UNKNOWN, /* IFT_STARLAN */
548 /* 0xc */ WTAP_ENCAP_RAW_IP, /* IFT_P10, IBM SP switch */
549 /* 0xd */ WTAP_ENCAP_UNKNOWN, /* IFT_P80 */
550 /* 0xe */ WTAP_ENCAP_UNKNOWN, /* IFT_HY */
551 /* 0xf */ WTAP_ENCAP_FDDI_BITSWAPPED, /* IFT_FDDI */
552 /* 0x10 */ WTAP_ENCAP_LAPB, /* IFT_LAPB */ /* no data to back this up */
553 /* 0x11 */ WTAP_ENCAP_UNKNOWN, /* IFT_SDLC */
554 /* 0x12 */ WTAP_ENCAP_UNKNOWN, /* IFT_T1 */
555 /* 0x13 */ WTAP_ENCAP_UNKNOWN, /* IFT_CEPT */
556 /* 0x14 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNBASIC */
557 /* 0x15 */ WTAP_ENCAP_UNKNOWN, /* IFT_ISDNPRIMARY */
558 /* 0x16 */ WTAP_ENCAP_UNKNOWN, /* IFT_PTPSERIAL */
559 /* 0x17 */ WTAP_ENCAP_UNKNOWN, /* IFT_PPP */
560 /* 0x18 */ WTAP_ENCAP_RAW_IP, /* IFT_LOOP */
561 /* 0x19 */ WTAP_ENCAP_UNKNOWN, /* IFT_EON */
562 /* 0x1a */ WTAP_ENCAP_UNKNOWN, /* IFT_XETHER */
563 /* 0x1b */ WTAP_ENCAP_UNKNOWN, /* IFT_NSIP */
564 /* 0x1c */ WTAP_ENCAP_UNKNOWN, /* IFT_SLIP */
565 /* 0x1d */ WTAP_ENCAP_UNKNOWN, /* IFT_ULTRA */
566 /* 0x1e */ WTAP_ENCAP_UNKNOWN, /* IFT_DS3 */
567 /* 0x1f */ WTAP_ENCAP_UNKNOWN, /* IFT_SIP */
568 /* 0x20 */ WTAP_ENCAP_UNKNOWN, /* IFT_FRELAY */
569 /* 0x21 */ WTAP_ENCAP_UNKNOWN, /* IFT_RS232 */
570 /* 0x22 */ WTAP_ENCAP_UNKNOWN, /* IFT_PARA */
571 /* 0x23 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNET */
572 /* 0x24 */ WTAP_ENCAP_UNKNOWN, /* IFT_ARCNETPLUS */
573 /* 0x25 */ WTAP_ENCAP_ATM_PDUS, /* IFT_ATM */
575 #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])
577 if (ift < NUM_IFT_ENCAPS) {
578 return ift_encap[ift];
584 return WTAP_ENCAP_INFINIBAND;
587 /* Host Fabric Interface */
589 /* The HFI interface on AIX provides raw IP
590 in the packet trace. It's unclear if the HFI
591 can be configured for any other protocol, and if
592 any field in the iptrace header indicates what
593 that protocol is. For now, we are hard-coding
594 this as RAW_IP, but if we find another iptrace file
595 using HFI that provides another protocol, we will
596 have to figure out which field in the iptrace file
598 return WTAP_ENCAP_RAW_IP;
602 return WTAP_ENCAP_UNKNOWN;
608 * Editor modelines - http://www.wireshark.org/tools/modelines.html
613 * indent-tabs-mode: t
616 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
617 * :indentSize=8:tabSize=8:noTabs=false: