Give those capture file formats we can write a "short name", to be used
[obnox/wireshark/wip.git] / wiretap / libpcap.c
1 /* libpcap.c
2  *
3  * $Id: libpcap.c,v 1.26 1999/12/04 09:38:37 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <stdlib.h>
27 #include <errno.h>
28 #include "wtap.h"
29 #include "file.h"
30 #include "buffer.h"
31 #include "libpcap.h"
32
33 /* See source to the "libpcap" library for information on the "libpcap"
34    file format. */
35
36 /* Magic numbers in "libpcap" files.
37
38    "libpcap" file records are written in the byte order of the host that
39    writes them, and the reader is expected to fix this up.
40
41    PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
42    is a byte-swapped version of that.
43
44    PCAP_MODIFIED_MAGIC is for Alexey Kuznetsov's modified "libpcap"
45    format, as generated on Linux systems that have a "libpcap" with
46    his patches, at
47    
48         http://ftp.sunet.se/pub/os/Linux/ip-routing/lbl-tools/
49
50    applied; PCAP_SWAPPED_MODIFIED_MAGIC is the byte-swapped version. */
51 #define PCAP_MAGIC                      0xa1b2c3d4
52 #define PCAP_SWAPPED_MAGIC              0xd4c3b2a1
53 #define PCAP_MODIFIED_MAGIC             0xa1b2cd34
54 #define PCAP_SWAPPED_MODIFIED_MAGIC     0x34cdb2a1
55
56 /* Macros to byte-swap 32-bit and 16-bit quantities. */
57 #define BSWAP32(x) \
58         ((((x)&0xFF000000)>>24) | \
59          (((x)&0x00FF0000)>>8) | \
60          (((x)&0x0000FF00)<<8) | \
61          (((x)&0x000000FF)<<24))
62 #define BSWAP16(x) \
63          ((((x)&0xFF00)>>8) | \
64           (((x)&0x00FF)<<8))
65
66 /* On some systems, the FDDI MAC addresses are bit-swapped. */
67 #if !defined(ultrix) && !defined(__alpha) && !defined(__bsdi__)
68 #define BIT_SWAPPED_MAC_ADDRS
69 #endif
70
71 /* "libpcap" file header (minus magic number). */
72 struct pcap_hdr {
73         guint16 version_major;  /* major version number */
74         guint16 version_minor;  /* minor version number */
75         gint32  thiszone;       /* GMT to local correction */
76         guint32 sigfigs;        /* accuracy of timestamps */
77         guint32 snaplen;        /* max length of captured packets, in octets */
78         guint32 network;        /* data link type */
79 };
80
81 /* "libpcap" record header. */
82 struct pcaprec_hdr {
83         guint32 ts_sec;         /* timestamp seconds */
84         guint32 ts_usec;        /* timestamp microseconds */
85         guint32 incl_len;       /* number of octets of packet saved in file */
86         guint32 orig_len;       /* actual length of packet */
87 };
88
89 /* "libpcap" record header for Alexey's patched version. */
90 struct pcaprec_modified_hdr {
91         struct pcaprec_hdr hdr; /* the regular header */
92         guint32 ifindex;        /* index, in *capturing* machine's list of
93                                    interfaces, of the interface on which this
94                                    packet came in. */
95         guint16 protocol;       /* Ethernet packet type */
96         guint8 pkt_type;        /* broadcast/multicast/etc. indication */
97 };
98
99 static int libpcap_read(wtap *wth, int *err);
100 static void adjust_header(wtap *wth, struct pcaprec_hdr *hdr);
101 static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
102     const u_char *pd, int *err);
103
104 /*
105  * XXX - this is a bit of a mess.  OpenBSD, and perhaps NetBSD, and
106  * BSD/OS have different DLT_ codes from FreeBSD (and from the LBL
107  * BPF code), and, at least in some cases, from each other.
108  * For now, we simply treat those type values with different
109  * meanings on different platforms, except for DLT_RAW, as "unknown";
110  * this means you won't be able to capture from a network using those
111  * types in Ethereal (and that capturing from the loopback interface
112  * won't necessarily work right on OpenBSD, either, as it uses
113  * DLT_LOOP, which is the same as DLT_RAW on other platforms).
114  *
115  * Does anybody know what BSD/OS uses as DLT_ types for SLIP and
116  * PPP?  The LBL code, and the OpenBSD code, appear to disagree....
117  *
118  * Nothing in FreeBSD appears to use DLT_RAW, so it's not clear what
119  * link-layer header or fake header appears for DLT_RAW.  If it's
120  * completely unused, or if it behaves the same way OpenBSD DLT_LOOP
121  * behaves, i.e. it puts an address family in *network* byte order
122  * (as opposed to the *host* byte order that DLT_NULL uses on FreeBSD),
123  * then we should just make it WTAP_ENCAP_NULL, which we treat in
124  * such a fashion as to cause it to work with DLT_LOOP headers.
125  */
126 static const int pcap_encap[] = {
127         WTAP_ENCAP_NULL,        /* null encapsulation */
128         WTAP_ENCAP_ETHERNET,
129         WTAP_ENCAP_UNKNOWN,     /* 3Mb experimental Ethernet */
130         WTAP_ENCAP_UNKNOWN,     /* Amateur Radio AX.25 */
131         WTAP_ENCAP_UNKNOWN,     /* Proteon ProNET Token Ring */
132         WTAP_ENCAP_UNKNOWN,     /* Chaos */
133         WTAP_ENCAP_TR,          /* IEEE 802 Networks - assume token ring */
134         WTAP_ENCAP_ARCNET,
135         WTAP_ENCAP_SLIP,
136         WTAP_ENCAP_PPP,
137 #ifdef BIT_SWAPPED_MAC_ADDRS
138         WTAP_ENCAP_FDDI_BITSWAPPED,
139 #else
140         WTAP_ENCAP_FDDI,
141 #endif
142         WTAP_ENCAP_ATM_RFC1483, /* or, on BSD/OS, Frame Relay */
143         WTAP_ENCAP_RAW_IP,      /* or, on OpenBSD, DLT_LOOP, and on BSD/OS,
144                                    Cisco HDLC */
145         WTAP_ENCAP_UNKNOWN,     /* In LBL BPF and FreeBSD, BSD/OS SLIP;
146                                    on OpenBSD, DLT_ENC; on BSD/OS,
147                                    DLT_ATM_RFC1483 */
148         WTAP_ENCAP_UNKNOWN,     /* In LBL BPF and FreeBSD, BSD/OS PPP;
149                                    on OpenBSD and BSD/OS, DLT_RAW */
150         WTAP_ENCAP_UNKNOWN,     /* In OpenBSD and BSD/OS, BSD/OS SLIP,
151                                    but the BSD/OS header says "internal
152                                    to libpcap", whatever that means */
153         WTAP_ENCAP_UNKNOWN,     /* In OpenBSD and BSD/OS, BSD/OS PPP,
154                                    but the BSD/OS header says "internal
155                                    to libpcap", whatever that means */
156         WTAP_ENCAP_UNKNOWN,
157         WTAP_ENCAP_UNKNOWN,
158         WTAP_ENCAP_LINUX_ATM_CLIP
159 };
160 #define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0])
161
162 int libpcap_open(wtap *wth, int *err)
163 {
164         int bytes_read;
165         guint32 magic;
166         struct pcap_hdr hdr;
167         gboolean byte_swapped;
168         gboolean modified;
169         struct pcaprec_hdr first_rec_hdr;
170         struct pcaprec_hdr second_rec_hdr;
171
172         /* Read in the number that should be at the start of a "libpcap" file */
173         file_seek(wth->fh, 0, SEEK_SET);
174         wth->data_offset = 0;
175         errno = WTAP_ERR_CANT_READ;
176         bytes_read = file_read(&magic, 1, sizeof magic, wth->fh);
177         if (bytes_read != sizeof magic) {
178                 *err = file_error(wth->fh);
179                 if (*err != 0)
180                         return -1;
181                 return 0;
182         }
183         wth->data_offset += sizeof magic;
184
185         switch (magic) {
186
187         case PCAP_MAGIC:
188                 /* Host that wrote it has our byte order. */
189                 byte_swapped = FALSE;
190                 modified = FALSE;
191                 break;
192
193         case PCAP_MODIFIED_MAGIC:
194                 /* Host that wrote it has our byte order, but was running
195                    a program using the patched "libpcap". */
196                 byte_swapped = FALSE;
197                 modified = TRUE;
198                 break;
199
200         case PCAP_SWAPPED_MAGIC:
201                 /* Host that wrote it has a byte order opposite to ours. */
202                 byte_swapped = TRUE;
203                 modified = FALSE;
204                 break;
205
206         case PCAP_SWAPPED_MODIFIED_MAGIC:
207                 /* Host that wrote it out has a byte order opposite to
208                    ours, and was running a program using the patched
209                    "libpcap". */
210                 byte_swapped = TRUE;
211                 modified = TRUE;
212                 break;
213
214         default:
215                 /* Not a "libpcap" type we know about. */
216                 return 0;
217         }
218
219         /* Read the rest of the header. */
220         errno = WTAP_ERR_CANT_READ;
221         bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
222         if (bytes_read != sizeof hdr) {
223                 *err = file_error(wth->fh);
224                 if (*err != 0)
225                         return -1;
226                 return 0;
227         }
228         wth->data_offset += sizeof hdr;
229
230         if (byte_swapped) {
231                 /* Byte-swap the header fields about which we care. */
232                 hdr.version_major = BSWAP16(hdr.version_major);
233                 hdr.version_minor = BSWAP16(hdr.version_minor);
234                 hdr.snaplen = BSWAP32(hdr.snaplen);
235                 hdr.network = BSWAP32(hdr.network);
236         }
237         if (hdr.version_major < 2) {
238                 /* We only support version 2.0 and later. */
239                 g_message("pcap: major version %u unsupported",
240                     hdr.version_major);
241                 *err = WTAP_ERR_UNSUPPORTED;
242                 return -1;
243         }
244         if (hdr.network >= NUM_PCAP_ENCAPS
245             || pcap_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
246                 g_message("pcap: network type %u unknown or unsupported",
247                     hdr.network);
248                 *err = WTAP_ERR_UNSUPPORTED;
249                 return -1;
250         }
251
252         /* This is a libpcap file */
253         wth->file_type = modified ? WTAP_FILE_PCAP_MODIFIED : WTAP_FILE_PCAP;
254         wth->capture.pcap = g_malloc(sizeof(libpcap_t));
255         wth->capture.pcap->byte_swapped = byte_swapped;
256         wth->capture.pcap->modified = modified;
257         wth->capture.pcap->version_major = hdr.version_major;
258         wth->capture.pcap->version_minor = hdr.version_minor;
259         wth->subtype_read = libpcap_read;
260         wth->file_encap = pcap_encap[hdr.network];
261         wth->snapshot_length = hdr.snaplen;
262
263         /*
264          * Is this a capture file with the non-modified magic number?
265          */
266         if (!wth->capture.pcap->modified) {
267                 /*
268                  * Yes.  Let's look at the header for the first record,
269                  * and see if, interpreting it as a non-modified header,
270                  * the position where it says the header for the
271                  * *second* record is contains a corrupted header.
272                  *
273                  * If so, this may be a modified capture file with a
274                  * non-modified magic number - in some versions of
275                  * Alexey's patches, the packet header format was
276                  * changed but the magic number wasn't, and, alas,
277                  * Red Hat appear to have picked up one of those
278                  * patches for RH 6.1, meaning RH 6.1 has a "tcpdump"
279                  * that writes out files that can't be read by any software
280                  * that expects non-modified headers if the magic number isn't
281                  * the modified magic number (e.g., any normal version of
282                  * "tcpdump", and Ethereal if we don't do this gross
283                  * heuristic).
284                  */
285                 bytes_read = file_read(&first_rec_hdr, 1,
286                     sizeof first_rec_hdr, wth->fh);
287                 if (bytes_read != sizeof first_rec_hdr) {
288                         *err = file_error(wth->fh);
289                         if (*err != 0)
290                                 return -1;      /* failed to read it */
291
292                         /*
293                          * Short read - assume the file isn't modified,
294                          * and put the seek pointer back.  The attempt
295                          * to read the first packet will presumably get
296                          * the same short read.
297                          */
298                         goto give_up;
299                 }
300
301                 adjust_header(wth, &first_rec_hdr);
302
303                 if (first_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
304                         /*
305                          * The first record is bogus, so this is probably
306                          * a corrupt file.  Assume the file isn't modified,
307                          * and put the seek pointer back.  The attempt
308                          * to read the first packet will probably get
309                          * the same bogus length.
310                          */
311                         goto give_up;
312                 }
313
314                 file_seek(wth->fh,
315                     wth->data_offset + sizeof first_rec_hdr + first_rec_hdr.incl_len,
316                     SEEK_SET);
317                 bytes_read = file_read(&second_rec_hdr, 1,
318                     sizeof second_rec_hdr, wth->fh);
319
320                 /*
321                  * OK, does the next packet's header look sane?
322                  */
323                 if (bytes_read != sizeof second_rec_hdr) {
324                         *err = file_error(wth->fh);
325                         if (*err != 0)
326                                 return -1;      /* failed to read it */
327
328                         /*
329                          * Short read - assume the file isn't modified,
330                          * and put the seek pointer back.  The attempt
331                          * to read the second packet will presumably get
332                          * the same short read error.
333                          */
334                         goto give_up;
335                 }
336
337                 adjust_header(wth, &second_rec_hdr);
338                 if (second_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
339                         /*
340                          * Oh, dear.  Maybe it's a Capture File
341                          * From Hell, and what looks like the
342                          * "header" of the next packet is actually
343                          * random junk from the middle of a packet.
344                          * Try treating it as a modified file;
345                          * if that doesn't work, it probably *is*
346                          * a corrupt file.
347                          */
348                         wth->file_type = WTAP_FILE_PCAP_MODIFIED;
349                         wth->capture.pcap->modified = TRUE;
350                 }
351
352         give_up:
353                 /*
354                  * Restore the seek pointer.
355                  */
356                 file_seek(wth->fh, wth->data_offset, SEEK_SET);
357         }
358
359         return 1;
360 }
361
362 /* Read the next packet */
363 static int libpcap_read(wtap *wth, int *err)
364 {
365         guint   packet_size;
366         int     bytes_to_read, bytes_read;
367         struct pcaprec_modified_hdr hdr;
368         int     data_offset;
369
370         /* Read record header. */
371         errno = WTAP_ERR_CANT_READ;
372         bytes_to_read = wth->capture.pcap->modified ?
373             sizeof hdr : sizeof hdr.hdr;
374         bytes_read = file_read(&hdr, 1, bytes_to_read, wth->fh);
375         if (bytes_read != bytes_to_read) {
376                 *err = file_error(wth->fh);
377                 if (*err != 0)
378                         return -1;
379                 if (bytes_read != 0) {
380                         *err = WTAP_ERR_SHORT_READ;
381                         return -1;
382                 }
383                 return 0;
384         }
385         wth->data_offset += bytes_read;
386
387         adjust_header(wth, &hdr.hdr);
388
389         packet_size = hdr.hdr.incl_len;
390         if (packet_size > WTAP_MAX_PACKET_SIZE) {
391                 /*
392                  * Probably a corrupt capture file; don't blow up trying
393                  * to allocate space for an immensely-large packet.
394                  */
395                 g_message("pcap: File has %u-byte packet, bigger than maximum of %u",
396                     packet_size, WTAP_MAX_PACKET_SIZE);
397                 *err = WTAP_ERR_BAD_RECORD;
398                 return -1;
399         }
400
401         buffer_assure_space(wth->frame_buffer, packet_size);
402         data_offset = wth->data_offset;
403         errno = WTAP_ERR_CANT_READ;
404         bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
405                         packet_size, wth->fh);
406
407         if (bytes_read != packet_size) {
408                 *err = file_error(wth->fh);
409                 if (*err == 0)
410                         *err = WTAP_ERR_SHORT_READ;
411                 return -1;
412         }
413         wth->data_offset += packet_size;
414
415         wth->phdr.ts.tv_sec = hdr.hdr.ts_sec;
416         wth->phdr.ts.tv_usec = hdr.hdr.ts_usec;
417         wth->phdr.caplen = packet_size;
418         wth->phdr.len = hdr.hdr.orig_len;
419         wth->phdr.pkt_encap = wth->file_encap;
420
421         return data_offset;
422 }
423
424 static void
425 adjust_header(wtap *wth, struct pcaprec_hdr *hdr)
426 {
427         if (wth->capture.pcap->byte_swapped) {
428                 /* Byte-swap the record header fields. */
429                 hdr->ts_sec = BSWAP32(hdr->ts_sec);
430                 hdr->ts_usec = BSWAP32(hdr->ts_usec);
431                 hdr->incl_len = BSWAP32(hdr->incl_len);
432                 hdr->orig_len = BSWAP32(hdr->orig_len);
433         }
434
435         /* In file format version 2.3, the "incl_len" and "orig_len" fields
436            were swapped, in order to match the BPF header layout.
437
438            Unfortunately, some files were, according to a comment in the
439            "libpcap" source, written with version 2.3 in their headers
440            but without the interchanged fields, so if "incl_len" is
441            greater than "orig_len" - which would make no sense - we
442            assume that we need to swap them.  */
443         if (wth->capture.pcap->version_major == 2 &&
444             (wth->capture.pcap->version_minor < 3 ||
445              (wth->capture.pcap->version_minor == 3 &&
446               hdr->incl_len > hdr->orig_len))) {
447                 guint32 temp;
448
449                 temp = hdr->orig_len;
450                 hdr->orig_len = hdr->incl_len;
451                 hdr->incl_len = temp;
452         }
453 }
454
455 int wtap_pcap_encap_to_wtap_encap(int encap)
456 {
457         if (encap < 0 || encap >= NUM_PCAP_ENCAPS)
458                 return WTAP_ENCAP_UNKNOWN;
459         return pcap_encap[encap];
460 }
461
462 static const int wtap_encap[] = {
463         -1,             /* WTAP_ENCAP_UNKNOWN -> unsupported */
464         1,              /* WTAP_ENCAP_ETHERNET -> DLT_EN10MB */
465         6,              /* WTAP_ENCAP_TR -> DLT_IEEE802 */
466         8,              /* WTAP_ENCAP_SLIP -> DLT_SLIP */
467         9,              /* WTAP_ENCAP_PPP -> DLT_PPP */
468         10,             /* WTAP_ENCAP_FDDI -> DLT_FDDI */
469         10,             /* WTAP_ENCAP_FDDI_BITSWAPPED -> DLT_FDDI */
470         12,             /* WTAP_ENCAP_RAW_IP -> DLT_RAW */
471         7,              /* WTAP_ENCAP_ARCNET -> DLT_ARCNET */
472         11,             /* WTAP_ENCAP_ATM_RFC1483 -> DLT_ATM_RFC1483 */
473         19,             /* WTAP_ENCAP_LINUX_ATM_CLIP */
474         -1,             /* WTAP_ENCAP_LAPB -> unsupported*/
475         -1,             /* WTAP_ENCAP_ATM_SNIFFER -> unsupported */
476         0               /* WTAP_ENCAP_NULL -> DLT_NULL */
477 };
478 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
479
480 /* Returns 0 if we could write the specified encapsulation type,
481    an error indication otherwise. */
482 int libpcap_dump_can_write_encap(int filetype, int encap)
483 {
484         /* Per-packet encapsulations aren't supported. */
485         if (encap == WTAP_ENCAP_PER_PACKET)
486                 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
487
488         if (encap < 0 || encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
489                 return WTAP_ERR_UNSUPPORTED_ENCAP;
490
491         return 0;
492 }
493
494 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
495    failure */
496 gboolean libpcap_dump_open(wtap_dumper *wdh, int *err)
497 {
498         static const guint32 pcap_magic = PCAP_MAGIC;
499         struct pcap_hdr file_hdr;
500         int nwritten;
501
502         /* This is a libpcap file */
503         wdh->subtype_write = libpcap_dump;
504         wdh->subtype_close = NULL;
505
506         /* Write the file header. */
507         nwritten = fwrite(&pcap_magic, 1, sizeof pcap_magic, wdh->fh);
508         if (nwritten != sizeof pcap_magic) {
509                 if (nwritten < 0)
510                         *err = errno;
511                 else
512                         *err = WTAP_ERR_SHORT_WRITE;
513                 return FALSE;
514         }
515
516         /* current "libpcap" format is 2.4 */
517         file_hdr.version_major = 2;
518         file_hdr.version_minor = 4;
519         file_hdr.thiszone = 0;  /* XXX - current offset? */
520         file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
521         file_hdr.snaplen = wdh->snaplen;
522         file_hdr.network = wtap_encap[wdh->encap];
523         nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
524         if (nwritten != sizeof file_hdr) {
525                 if (nwritten < 0)
526                         *err = errno;
527                 else
528                         *err = WTAP_ERR_SHORT_WRITE;
529                 return FALSE;
530         }
531
532         return TRUE;
533 }
534
535 /* Write a record for a packet to a dump file.
536    Returns TRUE on success, FALSE on failure. */
537 static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
538     const u_char *pd, int *err)
539 {
540         struct pcaprec_hdr rec_hdr;
541         int nwritten;
542
543         rec_hdr.ts_sec = phdr->ts.tv_sec;
544         rec_hdr.ts_usec = phdr->ts.tv_usec;
545         rec_hdr.incl_len = phdr->caplen;
546         rec_hdr.orig_len = phdr->len;
547         nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
548         if (nwritten != sizeof rec_hdr) {
549                 if (nwritten < 0)
550                         *err = errno;
551                 else
552                         *err = WTAP_ERR_SHORT_WRITE;
553                 return FALSE;
554         }
555         nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
556         if (nwritten != phdr->caplen) {
557                 if (nwritten < 0)
558                         *err = errno;
559                 else
560                         *err = WTAP_ERR_SHORT_WRITE;
561                 return FALSE;
562         }
563         return TRUE;
564 }