The "file types" we have are actually combinations of types and
[metze/wireshark/wip.git] / wiretap / iptrace.c
1 /* iptrace.c
2  *
3  * $Id$
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21  *
22  */
23 #include "config.h"
24 #include <stdlib.h>
25 #include <errno.h>
26 #include <string.h>
27 #include "wtap-int.h"
28 #include "file_wrappers.h"
29 #include "buffer.h"
30 #include "atm.h"
31 #include "iptrace.h"
32
33 #define IPTRACE_IFT_HF  0x3d    /* Support for PERCS IP-HFI*/
34 #define IPTRACE_IFT_IB  0xc7    /* IP over Infiniband. Number by IANA */
35
36 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
37     gint64 *data_offset);
38 static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
39     struct wtap_pkthdr *phdr, Buffer *buf, int packet_size,
40     int *err, gchar **err_info);
41
42 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
43     gint64 *data_offset);
44 static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
45     struct wtap_pkthdr *phdr, Buffer *buf, int packet_size,
46     int *err, gchar **err_info);
47
48 static int iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len,
49     int *err, gchar **err_info);
50 static gboolean iptrace_read_rec_data(FILE_T fh, Buffer *buf,
51     struct wtap_pkthdr *phdr, int *err, gchar **err_info);
52 static void fill_in_pseudo_header(int encap,
53     union wtap_pseudo_header *pseudo_header, guint8 *header);
54 static int wtap_encap_ift(unsigned int  ift);
55
56 int iptrace_open(wtap *wth, int *err, gchar **err_info)
57 {
58         int bytes_read;
59         char name[12];
60
61         errno = WTAP_ERR_CANT_READ;
62         bytes_read = file_read(name, 11, wth->fh);
63         if (bytes_read != 11) {
64                 *err = file_error(wth->fh, err_info);
65                 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
66                         return -1;
67                 return 0;
68         }
69         name[11] = '\0';
70
71         if (strcmp(name, "iptrace 1.0") == 0) {
72                 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_IPTRACE_1_0;
73                 wth->subtype_read = iptrace_read_1_0;
74                 wth->subtype_seek_read = iptrace_seek_read_1_0;
75                 wth->tsprecision = WTAP_FILE_TSPREC_SEC;
76         }
77         else if (strcmp(name, "iptrace 2.0") == 0) {
78                 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_IPTRACE_2_0;
79                 wth->subtype_read = iptrace_read_2_0;
80                 wth->subtype_seek_read = iptrace_seek_read_2_0;
81                 wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
82         }
83         else {
84                 return 0;
85         }
86
87         return 1;
88 }
89
90 /***********************************************************
91  * iptrace 1.0                                             *
92  ***********************************************************/
93
94 /*
95  * iptrace 1.0, discovered through inspection
96  *
97  * Packet record contains:
98  *
99  *      an initial header, with a length field and a time stamp, in
100  *      seconds since the Epoch;
101  *
102  *      data, with the specified length.
103  *
104  * The data contains:
105  *
106  *      a bunch of information about the packet;
107  *
108  *      padding, at least for FDDI;
109  *
110  *      the raw packet data.
111  */
112 typedef struct {
113 /* 0-3 */       guint32         pkt_length;     /* packet length + 0x16 */
114 /* 4-7 */       guint32         tv_sec;         /* time stamp, seconds since the Epoch */
115 /* 8-11 */      guint32         junk1;          /* ???, not time */
116 /* 12-15 */     char            if_name[4];     /* null-terminated */
117 /* 16-27 */     char            junk2[12];      /* ??? */
118 /* 28 */        guint8          if_type;        /* BSD net/if_types.h */
119 /* 29 */        guint8          tx_flag;        /* 0=receive, 1=transmit */
120 } iptrace_1_0_phdr;
121
122 #define IPTRACE_1_0_PHDR_SIZE   30      /* initial header plus packet data */
123 #define IPTRACE_1_0_PDATA_SIZE  22      /* packet data */
124
125 static gboolean
126 iptrace_read_rec_1_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
127     int *err, gchar **err_info)
128 {
129         guint8                  header[IPTRACE_1_0_PHDR_SIZE];
130         int                     ret;
131         iptrace_1_0_phdr        pkt_hdr;
132         guint32                 packet_size;
133
134         ret = iptrace_read_rec_header(fh, header, IPTRACE_1_0_PHDR_SIZE,
135             err, err_info);
136         if (ret <= 0) {
137                 /* Read error or EOF */
138                 return FALSE;
139         }
140
141         /*
142          * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
143          * value giving the type of the interface.  Check out the
144          * <net/if_types.h> header file.
145          */
146         pkt_hdr.if_type = header[28];
147         phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
148         if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
149                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
150                 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
151                     pkt_hdr.if_type);
152                 return FALSE;
153         }
154
155         /* Read the packet metadata */
156         packet_size = pntohl(&header[0]);
157         if (packet_size < IPTRACE_1_0_PDATA_SIZE) {
158                 /*
159                  * Uh-oh, the record isn't big enough to even have a
160                  * packet meta-data header.
161                  */
162                 *err = WTAP_ERR_BAD_FILE;
163                 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
164                     packet_size);
165                 return FALSE;
166         }
167         packet_size -= IPTRACE_1_0_PDATA_SIZE;
168
169         /*
170          * AIX appears to put 3 bytes of padding in front of FDDI
171          * frames; strip that crap off.
172          */
173         if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
174                 /*
175                  * The packet size is really a record size and includes
176                  * the padding.
177                  */
178                 if (packet_size < 3) {
179                         /*
180                          * Uh-oh, the record isn't big enough to even have
181                          * the padding.
182                          */
183                         *err = WTAP_ERR_BAD_FILE;
184                         *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
185                             packet_size + IPTRACE_1_0_PDATA_SIZE);
186                         return FALSE;
187                 }
188                 packet_size -= 3;
189
190                 /*
191                  * Skip the padding.
192                  */
193                 if (!file_skip(fh, 3, err))
194                         return FALSE;
195         }
196         if (packet_size > WTAP_MAX_PACKET_SIZE) {
197                 /*
198                  * Probably a corrupt capture file; don't blow up trying
199                  * to allocate space for an immensely-large packet.
200                  */
201                 *err = WTAP_ERR_BAD_FILE;
202                 *err_info = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
203                     packet_size, WTAP_MAX_PACKET_SIZE);
204                 return FALSE;
205         }
206
207         phdr->presence_flags = WTAP_HAS_TS;
208         phdr->len = packet_size;
209         phdr->caplen = packet_size;
210         phdr->ts.secs = pntohl(&header[4]);
211         phdr->ts.nsecs = 0;
212
213         /* Fill in the pseudo-header. */
214         fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
215
216         /* Get the packet data */
217         return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
218 }
219
220 /* Read the next packet */
221 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
222     gint64 *data_offset)
223 {
224         *data_offset = file_tell(wth->fh);
225
226         /* Read the packet */
227         if (!iptrace_read_rec_1_0(wth->fh, &wth->phdr, wth->frame_buffer,
228             err, err_info)) {
229                 /* Read error or EOF */
230                 return FALSE;
231         }
232
233         /* If the per-file encapsulation isn't known, set it to this
234            packet's encapsulation.
235
236            If it *is* known, and it isn't this packet's encapsulation,
237            set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
238            have a single encapsulation for all packets in the file. */
239         if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
240                 wth->file_encap = wth->phdr.pkt_encap;
241         else {
242                 if (wth->file_encap != wth->phdr.pkt_encap)
243                         wth->file_encap = WTAP_ENCAP_PER_PACKET;
244         }
245
246         return TRUE;
247 }
248
249 static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
250     struct wtap_pkthdr *phdr, Buffer *buf, int packet_size _U_,
251     int *err, gchar **err_info)
252 {
253         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
254                 return FALSE;
255
256         /* Read the packet */
257         if (!iptrace_read_rec_1_0(wth->random_fh, phdr, buf, err, err_info)) {
258                 if (*err == 0)
259                         *err = WTAP_ERR_SHORT_READ;
260                 return FALSE;
261         }
262         return TRUE;
263 }
264
265 /***********************************************************
266  * iptrace 2.0                                             *
267  ***********************************************************/
268
269 /*
270  * iptrace 2.0, discovered through inspection
271  *
272  * Packet record contains:
273  *
274  *      an initial header, with a length field and a time stamp, in
275  *      seconds since the Epoch;
276  *
277  *      data, with the specified length.
278  *
279  * The data contains:
280  *
281  *      a bunch of information about the packet;
282  *
283  *      padding, at least for FDDI;
284  *
285  *      the raw packet data.
286  */
287 typedef struct {
288 /* 0-3 */       guint32         pkt_length;     /* packet length + 32 */
289 /* 4-7 */       guint32         tv_sec0;        /* time stamp, seconds since the Epoch */
290 /* 8-11 */      guint32         junk1;          /* ?? */
291 /* 12-15 */     char            if_name[4];     /* null-terminated */
292 /* 16-27 */     char            if_desc[12];    /* interface description. */
293 /* 28 */        guint8          if_type;        /* BSD net/if_types.h */
294 /* 29 */        guint8          tx_flag;        /* 0=receive, 1=transmit */
295 /* 30-31 */     guint16         junk3;
296 /* 32-35 */     guint32         tv_sec;         /* time stamp, seconds since the Epoch */
297 /* 36-39 */     guint32         tv_nsec;        /* nanoseconds since that second */
298 } iptrace_2_0_phdr;
299
300 #define IPTRACE_2_0_PHDR_SIZE   40      /* initial header plus packet data */
301 #define IPTRACE_2_0_PDATA_SIZE  32      /* packet data */
302
303 static gboolean
304 iptrace_read_rec_2_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
305     int *err, gchar **err_info)
306 {
307         guint8                  header[IPTRACE_2_0_PHDR_SIZE];
308         int                     ret;
309         iptrace_2_0_phdr        pkt_hdr;
310         guint32                 packet_size;
311
312         ret = iptrace_read_rec_header(fh, header, IPTRACE_2_0_PHDR_SIZE,
313             err, err_info);
314         if (ret <= 0) {
315                 /* Read error or EOF */
316                 return FALSE;
317         }
318
319         /*
320          * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
321          * value giving the type of the interface.  Check out the
322          * <net/if_types.h> header file.
323          */
324         pkt_hdr.if_type = header[28];
325         phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
326 #if 0
327         /*
328          * We used to error out if the interface type in iptrace was
329          * unknown/unhandled, but an iptrace may contain packets
330          * from a variety of interfaces, some known, and others
331          * unknown.
332          *
333          * It is better to display the data even for unknown interface
334          * types, isntead of erroring out. In the future, it would be
335          * nice to be able to flag which frames are shown as data
336          * because their interface type is unknown, and also present
337          * the interface type number to the user so that it can be
338          * reported easily back to the Wireshark developer.
339          *
340          * XXX - what types are there that are used in files but
341          * that we don't handle?
342          */
343         if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
344                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
345                 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
346                     pkt_hdr.if_type);
347                 return FALSE;
348         }
349 #endif
350
351         /* Read the packet metadata */
352         packet_size = pntohl(&header[0]);
353         if (packet_size < IPTRACE_2_0_PDATA_SIZE) {
354                 /*
355                  * Uh-oh, the record isn't big enough to even have a
356                  * packet meta-data header.
357                  */
358                 *err = WTAP_ERR_BAD_FILE;
359                 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
360                     packet_size);
361                 return FALSE;
362         }
363         packet_size -= IPTRACE_2_0_PDATA_SIZE;
364
365         /*
366          * AIX appears to put 3 bytes of padding in front of FDDI
367          * frames; strip that crap off.
368          */
369         if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
370                 /*
371                  * The packet size is really a record size and includes
372                  * the padding.
373                  */
374                 if (packet_size < 3) {
375                         /*
376                          * Uh-oh, the record isn't big enough to even have
377                          * the padding.
378                          */
379                         *err = WTAP_ERR_BAD_FILE;
380                         *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
381                             packet_size + IPTRACE_2_0_PDATA_SIZE);
382                         return FALSE;
383                 }
384                 packet_size -= 3;
385
386                 /*
387                  * Skip the padding.
388                  */
389                 if (!file_skip(fh, 3, err))
390                         return FALSE;
391         }
392         if (packet_size > WTAP_MAX_PACKET_SIZE) {
393                 /*
394                  * Probably a corrupt capture file; don't blow up trying
395                  * to allocate space for an immensely-large packet.
396                  */
397                 *err = WTAP_ERR_BAD_FILE;
398                 *err_info = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
399                     packet_size, WTAP_MAX_PACKET_SIZE);
400                 return FALSE;
401         }
402
403         phdr->presence_flags = WTAP_HAS_TS;
404         phdr->len = packet_size;
405         phdr->caplen = packet_size;
406         phdr->ts.secs = pntohl(&header[32]);
407         phdr->ts.nsecs = pntohl(&header[36]);
408
409         /* Fill in the pseudo_header. */
410         fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
411
412         /* Get the packet data */
413         return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
414 }
415
416 /* Read the next packet */
417 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
418     gint64 *data_offset)
419 {
420         *data_offset = file_tell(wth->fh);
421
422         /* Read the packet */
423         if (!iptrace_read_rec_2_0(wth->fh, &wth->phdr, wth->frame_buffer,
424             err, err_info)) {
425                 /* Read error or EOF */
426                 return FALSE;
427         }
428
429         /* If the per-file encapsulation isn't known, set it to this
430            packet's encapsulation.
431
432            If it *is* known, and it isn't this packet's encapsulation,
433            set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
434            have a single encapsulation for all packets in the file. */
435         if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
436                 wth->file_encap = wth->phdr.pkt_encap;
437         else {
438                 if (wth->file_encap != wth->phdr.pkt_encap)
439                         wth->file_encap = WTAP_ENCAP_PER_PACKET;
440         }
441
442         return TRUE;
443 }
444
445 static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
446     struct wtap_pkthdr *phdr, Buffer *buf, int packet_size _U_,
447     int *err, gchar **err_info)
448 {
449         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
450                 return FALSE;
451
452         /* Read the packet */
453         if (!iptrace_read_rec_2_0(wth->random_fh, phdr, buf, err, err_info)) {
454                 if (*err == 0)
455                         *err = WTAP_ERR_SHORT_READ;
456                 return FALSE;
457         }
458         return TRUE;
459 }
460
461 static int
462 iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len, int *err,
463     gchar **err_info)
464 {
465         int     bytes_read;
466
467         errno = WTAP_ERR_CANT_READ;
468         bytes_read = file_read(header, header_len, fh);
469         if (bytes_read != header_len) {
470                 *err = file_error(fh, err_info);
471                 if (*err != 0)
472                         return -1;
473                 if (bytes_read != 0) {
474                         *err = WTAP_ERR_SHORT_READ;
475                         return -1;
476                 }
477                 return 0;
478         }
479         return 1;
480 }
481
482 static gboolean
483 iptrace_read_rec_data(FILE_T fh, Buffer *buf, struct wtap_pkthdr *phdr,
484     int *err, gchar **err_info)
485 {
486         if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
487                 return FALSE;
488
489         if (phdr->pkt_encap == WTAP_ENCAP_ATM_PDUS) {
490                 /*
491                  * Attempt to guess from the packet data, the VPI,
492                  * and the VCI information about the type of traffic.
493                  */
494                 atm_guess_traffic_type(buffer_start_ptr(buf), phdr->caplen,
495                     &phdr->pseudo_header);
496         }
497
498         return TRUE;
499 }
500
501 /*
502  * Fill in the pseudo-header information we can.
503  *
504  * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic
505  * is in the packet - it was presumably run on a machine that was one of
506  * the endpoints of the connection, so in theory it could presumably have
507  * told us, but, for whatever reason, it failed to do so - perhaps the
508  * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't
509  * have access to that information (e.g., because it's in the ATM driver,
510  * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be
511  * handed up to some particular client, it doesn't know what that client is).
512  *
513  * We let our caller try to figure out what kind of traffic it is, either
514  * by guessing based on the VPI/VCI, guessing based on the header of the
515  * packet, seeing earlier traffic that set up the circuit and specified
516  * in some fashion what sort of traffic it is, or being told by the user.
517  */
518 static void
519 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
520     guint8 *header)
521 {
522         char    if_text[9];
523         char    *decimal;
524         int     Vpi = 0;
525         int     Vci = 0;
526
527         switch (encap) {
528
529         case WTAP_ENCAP_ATM_PDUS:
530                 /* Rip apart the "x.y" text into Vpi/Vci numbers */
531                 memcpy(if_text, &header[20], 8);
532                 if_text[8] = '\0';
533                 decimal = strchr(if_text, '.');
534                 if (decimal) {
535                         *decimal = '\0';
536                         Vpi = (int)strtoul(if_text, NULL, 10);
537                         decimal++;
538                         Vci = (int)strtoul(decimal, NULL, 10);
539                 }
540
541                 /*
542                  * OK, which value means "DTE->DCE" and which value means
543                  * "DCE->DTE"?
544                  */
545                 pseudo_header->atm.channel = header[29];
546
547                 pseudo_header->atm.vpi = Vpi;
548                 pseudo_header->atm.vci = Vci;
549
550                 /* We don't have this information */
551                 pseudo_header->atm.flags = 0;
552                 pseudo_header->atm.cells = 0;
553                 pseudo_header->atm.aal5t_u2u = 0;
554                 pseudo_header->atm.aal5t_len = 0;
555                 pseudo_header->atm.aal5t_chksum = 0;
556                 break;
557
558         case WTAP_ENCAP_ETHERNET:
559                 /* We assume there's no FCS in this frame. */
560                 pseudo_header->eth.fcs_len = 0;
561                 break;
562         }
563 }
564
565 /* Given an RFC1573 (SNMP ifType) interface type,
566  * return the appropriate Wiretap Encapsulation Type.
567  */
568 static int
569 wtap_encap_ift(unsigned int  ift)
570 {
571
572         static const int ift_encap[] = {
573 /* 0x0 */       WTAP_ENCAP_UNKNOWN,     /* nothing */
574 /* 0x1 */       WTAP_ENCAP_UNKNOWN,     /* IFT_OTHER */
575 /* 0x2 */       WTAP_ENCAP_UNKNOWN,     /* IFT_1822 */
576 /* 0x3 */       WTAP_ENCAP_UNKNOWN,     /* IFT_HDH1822 */
577 /* 0x4 */       WTAP_ENCAP_RAW_IP,      /* IFT_X25DDN */
578 /* 0x5 */       WTAP_ENCAP_UNKNOWN,     /* IFT_X25 */
579 /* 0x6 */       WTAP_ENCAP_ETHERNET,    /* IFT_ETHER */
580 /* 0x7 */       WTAP_ENCAP_ETHERNET,    /* IFT_ISO88023 */
581 /* 0x8 */       WTAP_ENCAP_UNKNOWN,     /* IFT_ISO88024 */
582 /* 0x9 */       WTAP_ENCAP_TOKEN_RING,  /* IFT_ISO88025 */
583 /* 0xa */       WTAP_ENCAP_UNKNOWN,     /* IFT_ISO88026 */
584 /* 0xb */       WTAP_ENCAP_UNKNOWN,     /* IFT_STARLAN */
585 /* 0xc */       WTAP_ENCAP_RAW_IP,      /* IFT_P10, IBM SP switch */
586 /* 0xd */       WTAP_ENCAP_UNKNOWN,     /* IFT_P80 */
587 /* 0xe */       WTAP_ENCAP_UNKNOWN,     /* IFT_HY */
588 /* 0xf */       WTAP_ENCAP_FDDI_BITSWAPPED,     /* IFT_FDDI */
589 /* 0x10 */      WTAP_ENCAP_LAPB,        /* IFT_LAPB */  /* no data to back this up */
590 /* 0x11 */      WTAP_ENCAP_UNKNOWN,     /* IFT_SDLC */
591 /* 0x12 */      WTAP_ENCAP_UNKNOWN,     /* IFT_T1 */
592 /* 0x13 */      WTAP_ENCAP_UNKNOWN,     /* IFT_CEPT */
593 /* 0x14 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ISDNBASIC */
594 /* 0x15 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ISDNPRIMARY */
595 /* 0x16 */      WTAP_ENCAP_UNKNOWN,     /* IFT_PTPSERIAL */
596 /* 0x17 */      WTAP_ENCAP_UNKNOWN,     /* IFT_PPP */
597 /* 0x18 */      WTAP_ENCAP_RAW_IP,      /* IFT_LOOP */
598 /* 0x19 */      WTAP_ENCAP_UNKNOWN,     /* IFT_EON */
599 /* 0x1a */      WTAP_ENCAP_UNKNOWN,     /* IFT_XETHER */
600 /* 0x1b */      WTAP_ENCAP_UNKNOWN,     /* IFT_NSIP */
601 /* 0x1c */      WTAP_ENCAP_UNKNOWN,     /* IFT_SLIP */
602 /* 0x1d */      WTAP_ENCAP_UNKNOWN,     /* IFT_ULTRA */
603 /* 0x1e */      WTAP_ENCAP_UNKNOWN,     /* IFT_DS3 */
604 /* 0x1f */      WTAP_ENCAP_UNKNOWN,     /* IFT_SIP */
605 /* 0x20 */      WTAP_ENCAP_UNKNOWN,     /* IFT_FRELAY */
606 /* 0x21 */      WTAP_ENCAP_UNKNOWN,     /* IFT_RS232 */
607 /* 0x22 */      WTAP_ENCAP_UNKNOWN,     /* IFT_PARA */
608 /* 0x23 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ARCNET */
609 /* 0x24 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ARCNETPLUS */
610 /* 0x25 */      WTAP_ENCAP_ATM_PDUS,    /* IFT_ATM */
611         };
612         #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])
613
614         if (ift < NUM_IFT_ENCAPS) {
615                 return ift_encap[ift];
616         }
617         else {
618                 switch(ift) {
619                         /* Infiniband*/
620                         case IPTRACE_IFT_IB:
621                                 return WTAP_ENCAP_INFINIBAND;
622                                 break;
623
624                         /* Host Fabric Interface */
625                         case IPTRACE_IFT_HF:
626                                 /* The HFI interface on AIX provides raw IP
627                                 in the packet trace. It's unclear if the HFI
628                                 can be configured for any other protocol, and if
629                                 any field in the iptrace header indicates what
630                                 that protocol is. For now, we are hard-coding
631                                 this as RAW_IP, but if we find another iptrace file
632                                 using HFI that provides another protocol, we will
633                                 have to figure out which field in the iptrace file
634                                 encodes it. */
635                                 return WTAP_ENCAP_RAW_IP;
636                                 break;
637
638                         default:
639                                 return WTAP_ENCAP_UNKNOWN;
640                 }
641         }
642 }