Rename buffer_ routines to ws_buffer_ to avoid name collisions.
[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 <wsutil/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->rec_type = REC_TYPE_PACKET;
204         phdr->presence_flags = WTAP_HAS_TS;
205         phdr->len = packet_size;
206         phdr->caplen = packet_size;
207         phdr->ts.secs = pntoh32(&header[4]);
208         phdr->ts.nsecs = 0;
209
210         /* Fill in the pseudo-header. */
211         fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
212
213         /* Get the packet data */
214         return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
215 }
216
217 /* Read the next packet */
218 static gboolean iptrace_read_1_0(wtap *wth, int *err, gchar **err_info,
219     gint64 *data_offset)
220 {
221         *data_offset = file_tell(wth->fh);
222
223         /* Read the packet */
224         if (!iptrace_read_rec_1_0(wth->fh, &wth->phdr, wth->frame_buffer,
225             err, err_info)) {
226                 /* Read error or EOF */
227                 return FALSE;
228         }
229
230         /* If the per-file encapsulation isn't known, set it to this
231            packet's encapsulation.
232
233            If it *is* known, and it isn't this packet's encapsulation,
234            set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
235            have a single encapsulation for all packets in the file. */
236         if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
237                 wth->file_encap = wth->phdr.pkt_encap;
238         else {
239                 if (wth->file_encap != wth->phdr.pkt_encap)
240                         wth->file_encap = WTAP_ENCAP_PER_PACKET;
241         }
242
243         return TRUE;
244 }
245
246 static gboolean iptrace_seek_read_1_0(wtap *wth, gint64 seek_off,
247     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
248 {
249         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
250                 return FALSE;
251
252         /* Read the packet */
253         if (!iptrace_read_rec_1_0(wth->random_fh, phdr, buf, err, err_info)) {
254                 if (*err == 0)
255                         *err = WTAP_ERR_SHORT_READ;
256                 return FALSE;
257         }
258         return TRUE;
259 }
260
261 /***********************************************************
262  * iptrace 2.0                                             *
263  ***********************************************************/
264
265 /*
266  * iptrace 2.0, discovered through inspection
267  *
268  * Packet record contains:
269  *
270  *      an initial header, with a length field and a time stamp, in
271  *      seconds since the Epoch;
272  *
273  *      data, with the specified length.
274  *
275  * The data contains:
276  *
277  *      a bunch of information about the packet;
278  *
279  *      padding, at least for FDDI;
280  *
281  *      the raw packet data.
282  */
283 typedef struct {
284 /* 0-3 */       guint32         pkt_length;     /* packet length + 32 */
285 /* 4-7 */       guint32         tv_sec0;        /* time stamp, seconds since the Epoch */
286 /* 8-11 */      guint32         junk1;          /* ?? */
287 /* 12-15 */     char            if_name[4];     /* null-terminated */
288 /* 16-27 */     char            if_desc[12];    /* interface description. */
289 /* 28 */        guint8          if_type;        /* BSD net/if_types.h */
290 /* 29 */        guint8          tx_flag;        /* 0=receive, 1=transmit */
291 /* 30-31 */     guint16         junk3;
292 /* 32-35 */     guint32         tv_sec;         /* time stamp, seconds since the Epoch */
293 /* 36-39 */     guint32         tv_nsec;        /* nanoseconds since that second */
294 } iptrace_2_0_phdr;
295
296 #define IPTRACE_2_0_PHDR_SIZE   40      /* initial header plus packet data */
297 #define IPTRACE_2_0_PDATA_SIZE  32      /* packet data */
298
299 static gboolean
300 iptrace_read_rec_2_0(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
301     int *err, gchar **err_info)
302 {
303         guint8                  header[IPTRACE_2_0_PHDR_SIZE];
304         int                     ret;
305         iptrace_2_0_phdr        pkt_hdr;
306         guint32                 packet_size;
307
308         ret = iptrace_read_rec_header(fh, header, IPTRACE_2_0_PHDR_SIZE,
309             err, err_info);
310         if (ret <= 0) {
311                 /* Read error or EOF */
312                 return FALSE;
313         }
314
315         /*
316          * Byte 28 of the frame header appears to be a BSD-style IFT_xxx
317          * value giving the type of the interface.  Check out the
318          * <net/if_types.h> header file.
319          */
320         pkt_hdr.if_type = header[28];
321         phdr->pkt_encap = wtap_encap_ift(pkt_hdr.if_type);
322 #if 0
323         /*
324          * We used to error out if the interface type in iptrace was
325          * unknown/unhandled, but an iptrace may contain packets
326          * from a variety of interfaces, some known, and others
327          * unknown.
328          *
329          * It is better to display the data even for unknown interface
330          * types, isntead of erroring out. In the future, it would be
331          * nice to be able to flag which frames are shown as data
332          * because their interface type is unknown, and also present
333          * the interface type number to the user so that it can be
334          * reported easily back to the Wireshark developer.
335          *
336          * XXX - what types are there that are used in files but
337          * that we don't handle?
338          */
339         if (phdr->pkt_encap == WTAP_ENCAP_UNKNOWN) {
340                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
341                 *err_info = g_strdup_printf("iptrace: interface type IFT=0x%02x unknown or unsupported",
342                     pkt_hdr.if_type);
343                 return FALSE;
344         }
345 #endif
346
347         /* Read the packet metadata */
348         packet_size = pntoh32(&header[0]);
349         if (packet_size < IPTRACE_2_0_PDATA_SIZE) {
350                 /*
351                  * Uh-oh, the record isn't big enough to even have a
352                  * packet meta-data header.
353                  */
354                 *err = WTAP_ERR_BAD_FILE;
355                 *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
356                     packet_size);
357                 return FALSE;
358         }
359         packet_size -= IPTRACE_2_0_PDATA_SIZE;
360
361         /*
362          * AIX appears to put 3 bytes of padding in front of FDDI
363          * frames; strip that crap off.
364          */
365         if (phdr->pkt_encap == WTAP_ENCAP_FDDI_BITSWAPPED) {
366                 /*
367                  * The packet size is really a record size and includes
368                  * the padding.
369                  */
370                 if (packet_size < 3) {
371                         /*
372                          * Uh-oh, the record isn't big enough to even have
373                          * the padding.
374                          */
375                         *err = WTAP_ERR_BAD_FILE;
376                         *err_info = g_strdup_printf("iptrace: file has a %u-byte record, too small to have even a packet meta-data header",
377                             packet_size + IPTRACE_2_0_PDATA_SIZE);
378                         return FALSE;
379                 }
380                 packet_size -= 3;
381
382                 /*
383                  * Skip the padding.
384                  */
385                 if (!file_skip(fh, 3, err))
386                         return FALSE;
387         }
388         if (packet_size > WTAP_MAX_PACKET_SIZE) {
389                 /*
390                  * Probably a corrupt capture file; don't blow up trying
391                  * to allocate space for an immensely-large packet.
392                  */
393                 *err = WTAP_ERR_BAD_FILE;
394                 *err_info = g_strdup_printf("iptrace: File has %u-byte packet, bigger than maximum of %u",
395                     packet_size, WTAP_MAX_PACKET_SIZE);
396                 return FALSE;
397         }
398
399         phdr->rec_type = REC_TYPE_PACKET;
400         phdr->presence_flags = WTAP_HAS_TS;
401         phdr->len = packet_size;
402         phdr->caplen = packet_size;
403         phdr->ts.secs = pntoh32(&header[32]);
404         phdr->ts.nsecs = pntoh32(&header[36]);
405
406         /* Fill in the pseudo_header. */
407         fill_in_pseudo_header(phdr->pkt_encap, &phdr->pseudo_header, header);
408
409         /* Get the packet data */
410         return iptrace_read_rec_data(fh, buf, phdr, err, err_info);
411 }
412
413 /* Read the next packet */
414 static gboolean iptrace_read_2_0(wtap *wth, int *err, gchar **err_info,
415     gint64 *data_offset)
416 {
417         *data_offset = file_tell(wth->fh);
418
419         /* Read the packet */
420         if (!iptrace_read_rec_2_0(wth->fh, &wth->phdr, wth->frame_buffer,
421             err, err_info)) {
422                 /* Read error or EOF */
423                 return FALSE;
424         }
425
426         /* If the per-file encapsulation isn't known, set it to this
427            packet's encapsulation.
428
429            If it *is* known, and it isn't this packet's encapsulation,
430            set it to WTAP_ENCAP_PER_PACKET, as this file doesn't
431            have a single encapsulation for all packets in the file. */
432         if (wth->file_encap == WTAP_ENCAP_UNKNOWN)
433                 wth->file_encap = wth->phdr.pkt_encap;
434         else {
435                 if (wth->file_encap != wth->phdr.pkt_encap)
436                         wth->file_encap = WTAP_ENCAP_PER_PACKET;
437         }
438
439         return TRUE;
440 }
441
442 static gboolean iptrace_seek_read_2_0(wtap *wth, gint64 seek_off,
443     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
444 {
445         if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
446                 return FALSE;
447
448         /* Read the packet */
449         if (!iptrace_read_rec_2_0(wth->random_fh, phdr, buf, err, err_info)) {
450                 if (*err == 0)
451                         *err = WTAP_ERR_SHORT_READ;
452                 return FALSE;
453         }
454         return TRUE;
455 }
456
457 static int
458 iptrace_read_rec_header(FILE_T fh, guint8 *header, int header_len, int *err,
459     gchar **err_info)
460 {
461         int     bytes_read;
462
463         errno = WTAP_ERR_CANT_READ;
464         bytes_read = file_read(header, header_len, fh);
465         if (bytes_read != header_len) {
466                 *err = file_error(fh, err_info);
467                 if (*err != 0)
468                         return -1;
469                 if (bytes_read != 0) {
470                         *err = WTAP_ERR_SHORT_READ;
471                         return -1;
472                 }
473                 return 0;
474         }
475         return 1;
476 }
477
478 static gboolean
479 iptrace_read_rec_data(FILE_T fh, Buffer *buf, struct wtap_pkthdr *phdr,
480     int *err, gchar **err_info)
481 {
482         if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
483                 return FALSE;
484
485         if (phdr->pkt_encap == WTAP_ENCAP_ATM_PDUS) {
486                 /*
487                  * Attempt to guess from the packet data, the VPI,
488                  * and the VCI information about the type of traffic.
489                  */
490                 atm_guess_traffic_type(phdr, ws_buffer_start_ptr(buf));
491         }
492
493         return TRUE;
494 }
495
496 /*
497  * Fill in the pseudo-header information we can.
498  *
499  * For ATM traffic, "iptrace", alas, doesn't tell us what type of traffic
500  * is in the packet - it was presumably run on a machine that was one of
501  * the endpoints of the connection, so in theory it could presumably have
502  * told us, but, for whatever reason, it failed to do so - perhaps the
503  * low-level mechanism that feeds the presumably-AAL5 frames to us doesn't
504  * have access to that information (e.g., because it's in the ATM driver,
505  * and the ATM driver merely knows that stuff on VPI/VCI X.Y should be
506  * handed up to some particular client, it doesn't know what that client is).
507  *
508  * We let our caller try to figure out what kind of traffic it is, either
509  * by guessing based on the VPI/VCI, guessing based on the header of the
510  * packet, seeing earlier traffic that set up the circuit and specified
511  * in some fashion what sort of traffic it is, or being told by the user.
512  */
513 static void
514 fill_in_pseudo_header(int encap, union wtap_pseudo_header *pseudo_header,
515     guint8 *header)
516 {
517         char    if_text[9];
518         char    *decimal;
519         int     Vpi = 0;
520         int     Vci = 0;
521
522         switch (encap) {
523
524         case WTAP_ENCAP_ATM_PDUS:
525                 /* Rip apart the "x.y" text into Vpi/Vci numbers */
526                 memcpy(if_text, &header[20], 8);
527                 if_text[8] = '\0';
528                 decimal = strchr(if_text, '.');
529                 if (decimal) {
530                         *decimal = '\0';
531                         Vpi = (int)strtoul(if_text, NULL, 10);
532                         decimal++;
533                         Vci = (int)strtoul(decimal, NULL, 10);
534                 }
535
536                 /*
537                  * OK, which value means "DTE->DCE" and which value means
538                  * "DCE->DTE"?
539                  */
540                 pseudo_header->atm.channel = header[29];
541
542                 pseudo_header->atm.vpi = Vpi;
543                 pseudo_header->atm.vci = Vci;
544
545                 /* We don't have this information */
546                 pseudo_header->atm.flags = 0;
547                 pseudo_header->atm.cells = 0;
548                 pseudo_header->atm.aal5t_u2u = 0;
549                 pseudo_header->atm.aal5t_len = 0;
550                 pseudo_header->atm.aal5t_chksum = 0;
551                 break;
552
553         case WTAP_ENCAP_ETHERNET:
554                 /* We assume there's no FCS in this frame. */
555                 pseudo_header->eth.fcs_len = 0;
556                 break;
557         }
558 }
559
560 /* Given an RFC1573 (SNMP ifType) interface type,
561  * return the appropriate Wiretap Encapsulation Type.
562  */
563 static int
564 wtap_encap_ift(unsigned int  ift)
565 {
566
567         static const int ift_encap[] = {
568 /* 0x0 */       WTAP_ENCAP_UNKNOWN,     /* nothing */
569 /* 0x1 */       WTAP_ENCAP_UNKNOWN,     /* IFT_OTHER */
570 /* 0x2 */       WTAP_ENCAP_UNKNOWN,     /* IFT_1822 */
571 /* 0x3 */       WTAP_ENCAP_UNKNOWN,     /* IFT_HDH1822 */
572 /* 0x4 */       WTAP_ENCAP_RAW_IP,      /* IFT_X25DDN */
573 /* 0x5 */       WTAP_ENCAP_UNKNOWN,     /* IFT_X25 */
574 /* 0x6 */       WTAP_ENCAP_ETHERNET,    /* IFT_ETHER */
575 /* 0x7 */       WTAP_ENCAP_ETHERNET,    /* IFT_ISO88023 */
576 /* 0x8 */       WTAP_ENCAP_UNKNOWN,     /* IFT_ISO88024 */
577 /* 0x9 */       WTAP_ENCAP_TOKEN_RING,  /* IFT_ISO88025 */
578 /* 0xa */       WTAP_ENCAP_UNKNOWN,     /* IFT_ISO88026 */
579 /* 0xb */       WTAP_ENCAP_UNKNOWN,     /* IFT_STARLAN */
580 /* 0xc */       WTAP_ENCAP_RAW_IP,      /* IFT_P10, IBM SP switch */
581 /* 0xd */       WTAP_ENCAP_UNKNOWN,     /* IFT_P80 */
582 /* 0xe */       WTAP_ENCAP_UNKNOWN,     /* IFT_HY */
583 /* 0xf */       WTAP_ENCAP_FDDI_BITSWAPPED,     /* IFT_FDDI */
584 /* 0x10 */      WTAP_ENCAP_LAPB,        /* IFT_LAPB */  /* no data to back this up */
585 /* 0x11 */      WTAP_ENCAP_UNKNOWN,     /* IFT_SDLC */
586 /* 0x12 */      WTAP_ENCAP_UNKNOWN,     /* IFT_T1 */
587 /* 0x13 */      WTAP_ENCAP_UNKNOWN,     /* IFT_CEPT */
588 /* 0x14 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ISDNBASIC */
589 /* 0x15 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ISDNPRIMARY */
590 /* 0x16 */      WTAP_ENCAP_UNKNOWN,     /* IFT_PTPSERIAL */
591 /* 0x17 */      WTAP_ENCAP_UNKNOWN,     /* IFT_PPP */
592 /* 0x18 */      WTAP_ENCAP_RAW_IP,      /* IFT_LOOP */
593 /* 0x19 */      WTAP_ENCAP_UNKNOWN,     /* IFT_EON */
594 /* 0x1a */      WTAP_ENCAP_UNKNOWN,     /* IFT_XETHER */
595 /* 0x1b */      WTAP_ENCAP_UNKNOWN,     /* IFT_NSIP */
596 /* 0x1c */      WTAP_ENCAP_UNKNOWN,     /* IFT_SLIP */
597 /* 0x1d */      WTAP_ENCAP_UNKNOWN,     /* IFT_ULTRA */
598 /* 0x1e */      WTAP_ENCAP_UNKNOWN,     /* IFT_DS3 */
599 /* 0x1f */      WTAP_ENCAP_UNKNOWN,     /* IFT_SIP */
600 /* 0x20 */      WTAP_ENCAP_UNKNOWN,     /* IFT_FRELAY */
601 /* 0x21 */      WTAP_ENCAP_UNKNOWN,     /* IFT_RS232 */
602 /* 0x22 */      WTAP_ENCAP_UNKNOWN,     /* IFT_PARA */
603 /* 0x23 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ARCNET */
604 /* 0x24 */      WTAP_ENCAP_UNKNOWN,     /* IFT_ARCNETPLUS */
605 /* 0x25 */      WTAP_ENCAP_ATM_PDUS,    /* IFT_ATM */
606         };
607         #define NUM_IFT_ENCAPS (sizeof ift_encap / sizeof ift_encap[0])
608
609         if (ift < NUM_IFT_ENCAPS) {
610                 return ift_encap[ift];
611         }
612         else {
613                 switch(ift) {
614                         /* Infiniband*/
615                         case IPTRACE_IFT_IB:
616                                 return WTAP_ENCAP_INFINIBAND;
617                                 break;
618
619                         /* Host Fabric Interface */
620                         case IPTRACE_IFT_HF:
621                                 /* The HFI interface on AIX provides raw IP
622                                 in the packet trace. It's unclear if the HFI
623                                 can be configured for any other protocol, and if
624                                 any field in the iptrace header indicates what
625                                 that protocol is. For now, we are hard-coding
626                                 this as RAW_IP, but if we find another iptrace file
627                                 using HFI that provides another protocol, we will
628                                 have to figure out which field in the iptrace file
629                                 encodes it. */
630                                 return WTAP_ENCAP_RAW_IP;
631                                 break;
632
633                         default:
634                                 return WTAP_ENCAP_UNKNOWN;
635                 }
636         }
637 }