3 * $Id: libpcap.c,v 1.26 1999/12/04 09:38:37 guy Exp $
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
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.
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.
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.
33 /* See source to the "libpcap" library for information on the "libpcap"
36 /* Magic numbers in "libpcap" files.
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.
41 PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
42 is a byte-swapped version of that.
44 PCAP_MODIFIED_MAGIC is for Alexey Kuznetsov's modified "libpcap"
45 format, as generated on Linux systems that have a "libpcap" with
48 http://ftp.sunet.se/pub/os/Linux/ip-routing/lbl-tools/
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
56 /* Macros to byte-swap 32-bit and 16-bit quantities. */
58 ((((x)&0xFF000000)>>24) | \
59 (((x)&0x00FF0000)>>8) | \
60 (((x)&0x0000FF00)<<8) | \
61 (((x)&0x000000FF)<<24))
63 ((((x)&0xFF00)>>8) | \
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
71 /* "libpcap" file header (minus magic number). */
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 */
81 /* "libpcap" record header. */
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 */
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
95 guint16 protocol; /* Ethernet packet type */
96 guint8 pkt_type; /* broadcast/multicast/etc. indication */
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);
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).
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....
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.
126 static const int pcap_encap[] = {
127 WTAP_ENCAP_NULL, /* null encapsulation */
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 */
137 #ifdef BIT_SWAPPED_MAC_ADDRS
138 WTAP_ENCAP_FDDI_BITSWAPPED,
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,
145 WTAP_ENCAP_UNKNOWN, /* In LBL BPF and FreeBSD, BSD/OS SLIP;
146 on OpenBSD, DLT_ENC; on BSD/OS,
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 */
158 WTAP_ENCAP_LINUX_ATM_CLIP
160 #define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0])
162 int libpcap_open(wtap *wth, int *err)
167 gboolean byte_swapped;
169 struct pcaprec_hdr first_rec_hdr;
170 struct pcaprec_hdr second_rec_hdr;
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);
183 wth->data_offset += sizeof magic;
188 /* Host that wrote it has our byte order. */
189 byte_swapped = FALSE;
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;
200 case PCAP_SWAPPED_MAGIC:
201 /* Host that wrote it has a byte order opposite to ours. */
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
215 /* Not a "libpcap" type we know about. */
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);
228 wth->data_offset += sizeof hdr;
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);
237 if (hdr.version_major < 2) {
238 /* We only support version 2.0 and later. */
239 g_message("pcap: major version %u unsupported",
241 *err = WTAP_ERR_UNSUPPORTED;
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",
248 *err = WTAP_ERR_UNSUPPORTED;
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;
264 * Is this a capture file with the non-modified magic number?
266 if (!wth->capture.pcap->modified) {
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.
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
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);
290 return -1; /* failed to read it */
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.
301 adjust_header(wth, &first_rec_hdr);
303 if (first_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
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.
315 wth->data_offset + sizeof first_rec_hdr + first_rec_hdr.incl_len,
317 bytes_read = file_read(&second_rec_hdr, 1,
318 sizeof second_rec_hdr, wth->fh);
321 * OK, does the next packet's header look sane?
323 if (bytes_read != sizeof second_rec_hdr) {
324 *err = file_error(wth->fh);
326 return -1; /* failed to read it */
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.
337 adjust_header(wth, &second_rec_hdr);
338 if (second_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
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*
348 wth->file_type = WTAP_FILE_PCAP_MODIFIED;
349 wth->capture.pcap->modified = TRUE;
354 * Restore the seek pointer.
356 file_seek(wth->fh, wth->data_offset, SEEK_SET);
362 /* Read the next packet */
363 static int libpcap_read(wtap *wth, int *err)
366 int bytes_to_read, bytes_read;
367 struct pcaprec_modified_hdr hdr;
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);
379 if (bytes_read != 0) {
380 *err = WTAP_ERR_SHORT_READ;
385 wth->data_offset += bytes_read;
387 adjust_header(wth, &hdr.hdr);
389 packet_size = hdr.hdr.incl_len;
390 if (packet_size > WTAP_MAX_PACKET_SIZE) {
392 * Probably a corrupt capture file; don't blow up trying
393 * to allocate space for an immensely-large packet.
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;
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);
407 if (bytes_read != packet_size) {
408 *err = file_error(wth->fh);
410 *err = WTAP_ERR_SHORT_READ;
413 wth->data_offset += packet_size;
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;
425 adjust_header(wtap *wth, struct pcaprec_hdr *hdr)
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);
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.
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))) {
449 temp = hdr->orig_len;
450 hdr->orig_len = hdr->incl_len;
451 hdr->incl_len = temp;
455 int wtap_pcap_encap_to_wtap_encap(int encap)
457 if (encap < 0 || encap >= NUM_PCAP_ENCAPS)
458 return WTAP_ENCAP_UNKNOWN;
459 return pcap_encap[encap];
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 */
478 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
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)
484 /* Per-packet encapsulations aren't supported. */
485 if (encap == WTAP_ENCAP_PER_PACKET)
486 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
488 if (encap < 0 || encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
489 return WTAP_ERR_UNSUPPORTED_ENCAP;
494 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
496 gboolean libpcap_dump_open(wtap_dumper *wdh, int *err)
498 static const guint32 pcap_magic = PCAP_MAGIC;
499 struct pcap_hdr file_hdr;
502 /* This is a libpcap file */
503 wdh->subtype_write = libpcap_dump;
504 wdh->subtype_close = NULL;
506 /* Write the file header. */
507 nwritten = fwrite(&pcap_magic, 1, sizeof pcap_magic, wdh->fh);
508 if (nwritten != sizeof pcap_magic) {
512 *err = WTAP_ERR_SHORT_WRITE;
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) {
528 *err = WTAP_ERR_SHORT_WRITE;
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)
540 struct pcaprec_hdr rec_hdr;
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) {
552 *err = WTAP_ERR_SHORT_WRITE;
555 nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
556 if (nwritten != phdr->caplen) {
560 *err = WTAP_ERR_SHORT_WRITE;