Allow wtap_read() and wtap_seek_read() to return non-packet records.
[metze/wireshark/wip.git] / wiretap / iptrace.c
1 /* iptrace.c
2  *
3  * Wiretap Library
4  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
5  *
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.
10  *
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.
15  *
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.
19  *
20  */
21 #include "config.h"
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <string.h>
25 #include "wtap-int.h"
26 #include "file_wrappers.h"
27 #include "buffer.h"
28 #include "atm.h"
29 #include "iptrace.h"
30
31 #define IPTRACE_IFT_HF  0x3d    /* Support for PERCS IP-HFI*/
32 #define IPTRACE_IFT_IB  0xc7    /* IP over Infiniband. Number by IANA */
33
34 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
35     gint64 *data_offset);
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);
38
39 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
40     gint64 *data_offset);
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);
43
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);
51
52 int iptrace_open(wtap *wth, int *err, gchar **err_info)
53 {
54         int bytes_read;
55         char name[12];
56
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)
62                         return -1;
63                 return 0;
64         }
65         name[11] = '\0';
66
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;
72         }
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;
78         }
79         else {
80                 return 0;
81         }
82
83         return 1;
84 }
85
86 /***********************************************************
87  * iptrace 1.0                                             *
88  ***********************************************************/
89
90 /*
91  * iptrace 1.0, discovered through inspection
92  *
93  * Packet record contains:
94  *
95  *      an initial header, with a length field and a time stamp, in
96  *      seconds since the Epoch;
97  *
98  *      data, with the specified length.
99  *
100  * The data contains:
101  *
102  *      a bunch of information about the packet;
103  *
104  *      padding, at least for FDDI;
105  *
106  *      the raw packet data.
107  */
108 typedef struct {
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 */
116 } iptrace_1_0_phdr;
117
118 #define IPTRACE_1_0_PHDR_SIZE   30      /* initial header plus packet data */
119 #define IPTRACE_1_0_PDATA_SIZE  22      /* packet data */
120
121 static gboolean
122 iptrace_read_rec_1_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
123     int *err, gchar **err_info)
124 {
125         guint8                  header[IPTRACE_1_0_PHDR_SIZE];
126         int                     ret;
127         iptrace_1_0_phdr        pkt_hdr;
128         guint32                 packet_size;
129
130         ret = iptrace_read_rec_header(fh, header, IPTRACE_1_0_PHDR_SIZE,
131             err, err_info);
132         if (ret <= 0) {
133                 /* Read error or EOF */
134                 return FALSE;
135         }
136
137         /*
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.
141          */
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",
147                     pkt_hdr.if_type);
148                 return FALSE;
149         }
150
151         /* Read the packet metadata */
152         packet_size = pntoh32(&header[0]);
153         if (packet_size < IPTRACE_1_0_PDATA_SIZE) {
154                 /*
155                  * Uh-oh, the record isn't big enough to even have a
156                  * packet meta-data header.
157                  */
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",
160                     packet_size);
161                 return FALSE;
162         }
163         packet_size -= IPTRACE_1_0_PDATA_SIZE;
164
165         /*
166          * AIX appears to put 3 bytes of padding in front of FDDI
167          * frames; strip that crap off.
168          */
169         if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
170                 /*
171                  * The packet size is really a record size and includes
172                  * the padding.
173                  */
174                 if (packet_size < 3) {
175                         /*
176                          * Uh-oh, the record isn't big enough to even have
177                          * the padding.
178                          */
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);
182                         return FALSE;
183                 }
184                 packet_size -= 3;
185
186                 /*
187                  * Skip the padding.
188                  */
189                 if (!file_skip(fh, 3, err))
190                         return FALSE;
191         }
192         if (packet_size > WTAP_MAX_PACKET_SIZE) {
193                 /*
194                  * Probably a corrupt capture file; don't blow up trying
195                  * to allocate space for an immensely-large packet.
196                  */
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);
200                 return FALSE;
201         }
202
203         phdr->presence_flags = WTAP_HAS_TS;
204         phdr->len = packet_size;
205         phdr->caplen = packet_size;
206         phdr->ts.secs = pntoh32(&header[4]);
207         phdr->ts.nsecs = 0;
208
209         /* Fill in the pseudo-header. */
210         fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
211
212         /* Get the packet data */
213         return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
214 }
215
216 /* Read the next packet */
217 static int iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
218     gint64 *data_offset)
219 {
220         *data_offset = file_tell(wth->fh);
221
222         /* Read the packet */
223         if (!iptrace_read_rec_1_0(wth->fh, &wth->phdr, wth->frame_buffer,
224             err, err_info)) {
225                 /* Read error or EOF */
226                 return -1;
227         }
228
229         /* If the per-file encapsulation isn't known, set it to this
230            packet's encapsulation.
231
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;
237         else {
238                 if (wth->file_encap != wth->phdr.pkt_encap)
239                         wth->file_encap = WTAP_ENCAP_PER_PACKET;
240         }
241
242         return REC_TYPE_PACKET;
243 }
244
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)
247 {
248         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
249                 return -1;
250
251         /* Read the packet */
252         if (!iptrace_read_rec_1_0(wth->random_fh, phdr, buf, err, err_info)) {
253                 if (*err == 0)
254                         *err = WTAP_ERR_SHORT_READ;
255                 return -1;
256         }
257         return REC_TYPE_PACKET;
258 }
259
260 /***********************************************************
261  * iptrace 2.0                                             *
262  ***********************************************************/
263
264 /*
265  * iptrace 2.0, discovered through inspection
266  *
267  * Packet record contains:
268  *
269  *      an initial header, with a length field and a time stamp, in
270  *      seconds since the Epoch;
271  *
272  *      data, with the specified length.
273  *
274  * The data contains:
275  *
276  *      a bunch of information about the packet;
277  *
278  *      padding, at least for FDDI;
279  *
280  *      the raw packet data.
281  */
282 typedef struct {
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 */
293 } iptrace_2_0_phdr;
294
295 #define IPTRACE_2_0_PHDR_SIZE   40      /* initial header plus packet data */
296 #define IPTRACE_2_0_PDATA_SIZE  32      /* packet data */
297
298 static gboolean
299 iptrace_read_rec_2_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
300     int *err, gchar **err_info)
301 {
302         guint8                  header[IPTRACE_2_0_PHDR_SIZE];
303         int                     ret;
304         iptrace_2_0_phdr        pkt_hdr;
305         guint32                 packet_size;
306
307         ret = iptrace_read_rec_header(fh, header, IPTRACE_2_0_PHDR_SIZE,
308             err, err_info);
309         if (ret <= 0) {
310                 /* Read error or EOF */
311                 return FALSE;
312         }
313
314         /*
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.
318          */
319         pkt_hdr.if_type = header[28];
320         phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
321 #if 0
322         /*
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
326          * unknown.
327          *
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.
334          *
335          * XXX - what types are there that are used in files but
336          * that we don't handle?
337          */
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",
341                     pkt_hdr.if_type);
342                 return FALSE;
343         }
344 #endif
345
346         /* Read the packet metadata */
347         packet_size = pntoh32(&header[0]);
348         if (packet_size < IPTRACE_2_0_PDATA_SIZE) {
349                 /*
350                  * Uh-oh, the record isn't big enough to even have a
351                  * packet meta-data header.
352                  */
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",
355                     packet_size);
356                 return FALSE;
357         }
358         packet_size -= IPTRACE_2_0_PDATA_SIZE;
359
360         /*
361          * AIX appears to put 3 bytes of padding in front of FDDI
362          * frames; strip that crap off.
363          */
364         if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
365                 /*
366                  * The packet size is really a record size and includes
367                  * the padding.
368                  */
369                 if (packet_size < 3) {
370                         /*
371                          * Uh-oh, the record isn't big enough to even have
372                          * the padding.
373                          */
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);
377                         return FALSE;
378                 }
379                 packet_size -= 3;
380
381                 /*
382                  * Skip the padding.
383                  */
384                 if (!file_skip(fh, 3, err))
385                         return FALSE;
386         }
387         if (packet_size > WTAP_MAX_PACKET_SIZE) {
388                 /*
389                  * Probably a corrupt capture file; don't blow up trying
390                  * to allocate space for an immensely-large packet.
391                  */
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);
395                 return FALSE;
396         }
397
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]);
403
404         /* Fill in the pseudo_header. */
405         fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
406
407         /* Get the packet data */
408         return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
409 }
410
411 /* Read the next packet */
412 static int iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
413     gint64 *data_offset)
414 {
415         *data_offset = file_tell(wth->fh);
416
417         /* Read the packet */
418         if (!iptrace_read_rec_2_0(wth->fh, &wth->phdr, wth->frame_buffer,
419             err, err_info)) {
420                 /* Read error or EOF */
421                 return -1;
422         }
423
424         /* If the per-file encapsulation isn't known, set it to this
425            packet's encapsulation.
426
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;
432         else {
433                 if (wth->file_encap != wth->phdr.pkt_encap)
434                         wth->file_encap = WTAP_ENCAP_PER_PACKET;
435         }
436
437         return REC_TYPE_PACKET;
438 }
439
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)
442 {
443         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
444                 return -1;
445
446         /* Read the packet */
447         if (!iptrace_read_rec_2_0(wth->random_fh, phdr, buf, err, err_info)) {
448                 if (*err == 0)
449                         *err = WTAP_ERR_SHORT_READ;
450                 return -1;
451         }
452         return REC_TYPE_PACKET;
453 }
454
455 static int
456 iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len, int *err,
457     gchar **err_info)
458 {
459         int     bytes_read;
460
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);
465                 if (*err != 0)
466                         return -1;
467                 if (bytes_read != 0) {
468                         *err = WTAP_ERR_SHORT_READ;
469                         return -1;
470                 }
471                 return 0;
472         }
473         return 1;
474 }
475
476 static gboolean
477 iptrace_read_rec_data(FILE_T fh, Buffer *buf, struct wtap_pkthdr *phdr,
478     int *err, gchar **err_info)
479 {
480         if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
481                 return FALSE;
482
483         if (phdr->pkt_encap == WTAP_ENCAP_ATM_PDUS) {
484                 /*
485                  * Attempt to guess from the packet data, the VPI,
486                  * and the VCI information about the type of traffic.
487                  */
488                 atm_guess_traffic_type(phdr, buffer_start_ptr(buf));
489         }
490
491         return TRUE;
492 }
493
494 /*
495  * Fill in the pseudo-header information we can.
496  *
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).
505  *
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.
510  */
511 static void
512 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
513     guint8 *header)
514 {
515         char    if_text[9];
516         char    *decimal;
517         int     Vpi = 0;
518         int     Vci = 0;
519
520         switch (encap) {
521
522         case WTAP_ENCAP_ATM_PDUS:
523                 /* Rip apart the "x.y" text into Vpi/Vci numbers */
524                 memcpy(if_text, &header[20], 8);
525                 if_text[8] = '\0';
526                 decimal = strchr(if_text, '.');
527                 if (decimal) {
528                         *decimal = '\0';
529                         Vpi = (int)strtoul(if_text, NULL, 10);
530                         decimal++;
531                         Vci = (int)strtoul(decimal, NULL, 10);
532                 }
533
534                 /*
535                  * OK, which value means "DTE->DCE" and which value means
536                  * "DCE->DTE"?
537                  */
538                 pseudo_header->atm.channel = header[29];
539
540                 pseudo_header->atm.vpi = Vpi;
541                 pseudo_header->atm.vci = Vci;
542
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;
549                 break;
550
551         case WTAP_ENCAP_ETHERNET:
552                 /* We assume there's no FCS in this frame. */
553                 pseudo_header->eth.fcs_len = 0;
554                 break;
555         }
556 }
557
558 /* Given an RFC1573 (SNMP ifType) interface type,
559  * return the appropriate Wiretap Encapsulation Type.
560  */
561 static int
562 wtap_encap_ift(unsigned int  ift)
563 {
564
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 */
604         };
605         #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])
606
607         if (ift < NUM_IFT_ENCAPS) {
608                 return ift_encap[ift];
609         }
610         else {
611                 switch(ift) {
612                         /* Infiniband*/
613                         case IPTRACE_IFT_IB:
614                                 return WTAP_ENCAP_INFINIBAND;
615                                 break;
616
617                         /* Host Fabric Interface */
618                         case IPTRACE_IFT_HF:
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
627                                 encodes it. */
628                                 return WTAP_ENCAP_RAW_IP;
629                                 break;
630
631                         default:
632                                 return WTAP_ENCAP_UNKNOWN;
633                 }
634         }
635 }