In the final scene of the horror movie, just when you think the monster
[obnox/wireshark/wip.git] / wiretap / libpcap.c
1 /* libpcap.c
2  *
3  * $Id: libpcap.c,v 1.36 2000/07/26 06:04:32 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@xiexie.org>
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-int.h"
29 #include "file_wrappers.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 /* On some systems, the FDDI MAC addresses are bit-swapped. */
57 #if !defined(ultrix) && !defined(__alpha) && !defined(__bsdi__)
58 #define BIT_SWAPPED_MAC_ADDRS
59 #endif
60
61 /* "libpcap" file header (minus magic number). */
62 struct pcap_hdr {
63         guint16 version_major;  /* major version number */
64         guint16 version_minor;  /* minor version number */
65         gint32  thiszone;       /* GMT to local correction */
66         guint32 sigfigs;        /* accuracy of timestamps */
67         guint32 snaplen;        /* max length of captured packets, in octets */
68         guint32 network;        /* data link type */
69 };
70
71 /* "libpcap" record header. */
72 struct pcaprec_hdr {
73         guint32 ts_sec;         /* timestamp seconds */
74         guint32 ts_usec;        /* timestamp microseconds */
75         guint32 incl_len;       /* number of octets of packet saved in file */
76         guint32 orig_len;       /* actual length of packet */
77 };
78
79 /* "libpcap" record header for Alexey's patched version. */
80 struct pcaprec_modified_hdr {
81         struct pcaprec_hdr hdr; /* the regular header */
82         guint32 ifindex;        /* index, in *capturing* machine's list of
83                                    interfaces, of the interface on which this
84                                    packet came in. */
85         guint16 protocol;       /* Ethernet packet type */
86         guint8 pkt_type;        /* broadcast/multicast/etc. indication */
87         guint8 pad;             /* pad to a 4-byte boundary */
88 };
89
90 /* "libpcap" record header for Alexey's patched version in its ss990915
91    incarnation; this version shows up in SuSE Linux 6.3. */
92 struct pcaprec_ss990915_hdr {
93         struct pcaprec_hdr hdr; /* the regular header */
94         guint32 ifindex;        /* index, in *capturing* machine's list of
95                                    interfaces, of the interface on which this
96                                    packet came in. */
97         guint16 protocol;       /* Ethernet packet type */
98         guint8 pkt_type;        /* broadcast/multicast/etc. indication */
99         guint8 cpu1, cpu2;      /* SMP debugging gunk? */
100         guint8 pad[3];          /* pad to a 4-byte boundary */
101 };
102
103 static int libpcap_read(wtap *wth, int *err);
104 static void adjust_header(wtap *wth, struct pcaprec_hdr *hdr);
105 static void libpcap_close(wtap *wth);
106 static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
107     const union wtap_pseudo_header *pseudo_header, const u_char *pd, int *err);
108
109 /*
110  * XXX - this is a bit of a mess.  OpenBSD, and perhaps NetBSD, and
111  * BSD/OS have different DLT_ codes from FreeBSD (and from the LBL
112  * BPF code), and, at least in some cases, from each other.
113  * For now, we simply treat those type values with different
114  * meanings on different platforms, except for DLT_RAW, as "unknown";
115  * this means you won't be able to capture from a network using those
116  * types in Ethereal (and that capturing from the loopback interface
117  * won't necessarily work right on OpenBSD, either, as it uses
118  * DLT_LOOP, which is the same as DLT_RAW on other platforms).
119  *
120  * Does anybody know what BSD/OS uses as DLT_ types for SLIP and
121  * PPP?  The LBL code, and the OpenBSD code, appear to disagree....
122  *
123  * Nothing in FreeBSD appears to use DLT_RAW, so it's not clear what
124  * link-layer header or fake header appears for DLT_RAW.  If it's
125  * completely unused, or if it behaves the same way OpenBSD DLT_LOOP
126  * behaves, i.e. it puts an address family in *network* byte order
127  * (as opposed to the *host* byte order that DLT_NULL uses on FreeBSD),
128  * then we should just make it WTAP_ENCAP_NULL, which we treat in
129  * such a fashion as to cause it to work with DLT_LOOP headers.
130  */
131 static const int pcap_encap[] = {
132         WTAP_ENCAP_NULL,        /* null encapsulation */
133         WTAP_ENCAP_ETHERNET,
134         WTAP_ENCAP_UNKNOWN,     /* 3Mb experimental Ethernet */
135         WTAP_ENCAP_UNKNOWN,     /* Amateur Radio AX.25 */
136         WTAP_ENCAP_UNKNOWN,     /* Proteon ProNET Token Ring */
137         WTAP_ENCAP_UNKNOWN,     /* Chaos */
138         WTAP_ENCAP_TR,          /* IEEE 802 Networks - assume token ring */
139         WTAP_ENCAP_ARCNET,
140         WTAP_ENCAP_SLIP,
141         WTAP_ENCAP_PPP,
142 #ifdef BIT_SWAPPED_MAC_ADDRS
143         WTAP_ENCAP_FDDI_BITSWAPPED,
144 #else
145         WTAP_ENCAP_FDDI,
146 #endif
147         WTAP_ENCAP_ATM_RFC1483, /* or, on BSD/OS, Frame Relay */
148         WTAP_ENCAP_RAW_IP,      /* or, on OpenBSD, DLT_LOOP, and on BSD/OS,
149                                    Cisco HDLC */
150         WTAP_ENCAP_UNKNOWN,     /* In LBL BPF and FreeBSD, BSD/OS SLIP;
151                                    on OpenBSD, DLT_ENC; on BSD/OS,
152                                    DLT_ATM_RFC1483 */
153         WTAP_ENCAP_UNKNOWN,     /* In LBL BPF and FreeBSD, BSD/OS PPP;
154                                    on OpenBSD and BSD/OS, DLT_RAW */
155         WTAP_ENCAP_UNKNOWN,     /* In OpenBSD and BSD/OS, BSD/OS SLIP,
156                                    but the BSD/OS header says "internal
157                                    to libpcap", whatever that means;
158                                    in Linux with the ISDN4Linux patches
159                                    applied to libpcap, DLT_I4L_RAWIP,
160                                    which looks just like DLT_RAW but
161                                    is given a different DLT_ code for
162                                    no obvious good reason */
163         WTAP_ENCAP_UNKNOWN,     /* In OpenBSD and BSD/OS, BSD/OS PPP,
164                                    but the BSD/OS header says "internal
165                                    to libpcap", whatever that means;
166                                    in Linux with the ISDN4Linux patches
167                                    applied to libpcap, DLT_I4L_IP,
168                                    which provides only a 2-octet
169                                    Ethernet type as a link-layer header,
170                                    with a type of 0xFFFF meaning
171                                    ETH_P_802_3, a "Dummy type for 802.3
172                                    frames" */
173         WTAP_ENCAP_UNKNOWN,
174         WTAP_ENCAP_UNKNOWN,
175         WTAP_ENCAP_LINUX_ATM_CLIP
176 };
177 #define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0])
178
179 int libpcap_open(wtap *wth, int *err)
180 {
181         int bytes_read;
182         guint32 magic;
183         struct pcap_hdr hdr;
184         gboolean byte_swapped;
185         gboolean modified;
186         struct pcaprec_modified_hdr first_rec_hdr;
187         struct pcaprec_modified_hdr second_rec_hdr;
188         int hdr_len;
189
190         /* Read in the number that should be at the start of a "libpcap" file */
191         file_seek(wth->fh, 0, SEEK_SET);
192         wth->data_offset = 0;
193         errno = WTAP_ERR_CANT_READ;
194         bytes_read = file_read(&magic, 1, sizeof magic, wth->fh);
195         if (bytes_read != sizeof magic) {
196                 *err = file_error(wth->fh);
197                 if (*err != 0)
198                         return -1;
199                 return 0;
200         }
201         wth->data_offset += sizeof magic;
202
203         switch (magic) {
204
205         case PCAP_MAGIC:
206                 /* Host that wrote it has our byte order, and was running
207                    a program using either standard or ss990417 libpcap. */
208                 byte_swapped = FALSE;
209                 modified = FALSE;
210                 break;
211
212         case PCAP_MODIFIED_MAGIC:
213                 /* Host that wrote it has our byte order, and was running
214                    a program using either ss990915 or ss991029 libpcap. */
215                 byte_swapped = FALSE;
216                 modified = TRUE;
217                 break;
218
219         case PCAP_SWAPPED_MAGIC:
220                 /* Host that wrote it has a byte order opposite to ours,
221                    and was running a program using either standard or
222                    ss990417 libpcap. */
223                 byte_swapped = TRUE;
224                 modified = FALSE;
225                 break;
226
227         case PCAP_SWAPPED_MODIFIED_MAGIC:
228                 /* Host that wrote it out has a byte order opposite to
229                    ours, and was running a program using either ss990915
230                    or ss991029 libpcap. */
231                 byte_swapped = TRUE;
232                 modified = TRUE;
233                 break;
234
235         default:
236                 /* Not a "libpcap" type we know about. */
237                 return 0;
238         }
239
240         /* Read the rest of the header. */
241         errno = WTAP_ERR_CANT_READ;
242         bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
243         if (bytes_read != sizeof hdr) {
244                 *err = file_error(wth->fh);
245                 if (*err != 0)
246                         return -1;
247                 return 0;
248         }
249         wth->data_offset += sizeof hdr;
250
251         if (byte_swapped) {
252                 /* Byte-swap the header fields about which we care. */
253                 hdr.version_major = BSWAP16(hdr.version_major);
254                 hdr.version_minor = BSWAP16(hdr.version_minor);
255                 hdr.snaplen = BSWAP32(hdr.snaplen);
256                 hdr.network = BSWAP32(hdr.network);
257         }
258         if (hdr.version_major < 2) {
259                 /* We only support version 2.0 and later. */
260                 g_message("pcap: major version %u unsupported",
261                     hdr.version_major);
262                 *err = WTAP_ERR_UNSUPPORTED;
263                 return -1;
264         }
265         if (hdr.network >= NUM_PCAP_ENCAPS
266             || pcap_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
267                 g_message("pcap: network type %u unknown or unsupported",
268                     hdr.network);
269                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
270                 return -1;
271         }
272
273         /* This is a libpcap file */
274         wth->file_type = modified ? WTAP_FILE_PCAP_SS991029 : WTAP_FILE_PCAP;
275         wth->capture.pcap = g_malloc(sizeof(libpcap_t));
276         wth->capture.pcap->byte_swapped = byte_swapped;
277         wth->capture.pcap->version_major = hdr.version_major;
278         wth->capture.pcap->version_minor = hdr.version_minor;
279         wth->subtype_read = libpcap_read;
280         wth->subtype_seek_read = wtap_def_seek_read;
281         wth->subtype_close = libpcap_close;
282         wth->file_encap = pcap_encap[hdr.network];
283         wth->snapshot_length = hdr.snaplen;
284
285         /*
286          * Yes.  Let's look at the header for the first record,
287          * and see if, interpreting it as a standard header (if the
288          * magic number was standard) or a modified header (if the
289          * magic number was modified), the position where it says the
290          * header for the *second* record is contains a corrupted header.
291          *
292          * If so, then:
293          *
294          *      If this file had the standard magic number, it may be
295          *      an ss990417 capture file - in that version of Alexey's
296          *      patch, the packet header format was changed but the
297          *      magic number wasn't, and, alas, Red Hat appear to have
298          *      picked up that version of the patch for RH 6.1, meaning
299          *      RH 6.1 has a tcpdump that writes out files that can't
300          *      be read by any software that expects non-modified headers
301          *      if the magic number isn't the modified magic number (e.g.,
302          *      any normal version of tcpdump, and Ethereal if we don't
303          *      do this gross heuristic).
304          *
305          *      If this file had the modified magic number, it may be
306          *      an ss990915 capture file - in that version of Alexey's
307          *      patch, the magic number was changed, but the record
308          *      header had some extra fields, and, alas, SuSE appear
309          *      to have picked up that version of the patch for SuSE
310          *      6.3, meaning that programs expecting the standard per-
311          *      packet header in captures with the modified magic number
312          *      can't read dumps from its tcpdump.
313          */
314         hdr_len = modified ? sizeof (struct pcaprec_modified_hdr) :
315                              sizeof (struct pcaprec_hdr);
316         bytes_read = file_read(&first_rec_hdr, 1, hdr_len, wth->fh);
317         if (bytes_read != hdr_len) {
318                 *err = file_error(wth->fh);
319                 if (*err != 0)
320                         return -1;      /* failed to read it */
321
322                 /*
323                  * Short read - assume the file isn't modified,
324                  * and put the seek pointer back.  The attempt
325                  * to read the first packet will presumably get
326                  * the same short read.
327                  */
328                 goto give_up;
329         }
330
331         adjust_header(wth, &first_rec_hdr.hdr);
332
333         if (first_rec_hdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
334                 /*
335                  * The first record is bogus, so this is probably
336                  * a corrupt file.  Assume the file has the
337                  * expected header type, and put the seek pointer
338                  * back.  The attempt to read the first packet will
339                  * probably get the same bogus length.
340                  */
341                 goto give_up;
342         }
343
344         file_seek(wth->fh,
345             wth->data_offset + hdr_len + first_rec_hdr.hdr.incl_len, SEEK_SET);
346         bytes_read = file_read(&second_rec_hdr, 1, hdr_len, wth->fh);
347
348         /*
349          * OK, does the next packet's header look sane?
350          */
351         if (bytes_read != hdr_len) {
352                 *err = file_error(wth->fh);
353                 if (*err != 0)
354                         return -1;      /* failed to read it */
355
356                 /*
357                  * Short read - assume the file has the expected
358                  * header type, and put the seek pointer back.  The
359                  * attempt to read the second packet will presumably get
360                  * the same short read error.
361                  */
362                 goto give_up;
363         }
364
365         adjust_header(wth, &second_rec_hdr.hdr);
366         if (second_rec_hdr.hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
367                 /*
368                  * Oh, dear.  Maybe it's a Capture File
369                  * From Hell, and what looks like the
370                  * "header" of the next packet is actually
371                  * random junk from the middle of a packet.
372                  * Try treating it as having the other type for
373                  * the magic number it had; if that doesn't work,
374                  * it probably *is* a corrupt file.
375                  */
376                 wth->file_type = modified ? WTAP_FILE_PCAP_SS990915 :
377                                             WTAP_FILE_PCAP_SS990417;
378         }
379
380 give_up:
381         /*
382          * Restore the seek pointer.
383          */
384         file_seek(wth->fh, wth->data_offset, SEEK_SET);
385
386         return 1;
387 }
388
389 /* Read the next packet */
390 static int libpcap_read(wtap *wth, int *err)
391 {
392         guint   packet_size;
393         int     bytes_to_read, bytes_read;
394         struct pcaprec_ss990915_hdr hdr;
395         int     data_offset;
396
397         /* Read record header. */
398         errno = WTAP_ERR_CANT_READ;
399         switch (wth->file_type) {
400
401         case WTAP_FILE_PCAP:
402                 bytes_to_read = sizeof (struct pcaprec_hdr);
403                 break;
404
405         case WTAP_FILE_PCAP_SS990417:
406         case WTAP_FILE_PCAP_SS991029:
407                 bytes_to_read = sizeof (struct pcaprec_modified_hdr);
408                 break;
409
410         case WTAP_FILE_PCAP_SS990915:
411                 bytes_to_read = sizeof (struct pcaprec_ss990915_hdr);
412                 break;
413
414         default:
415                 g_assert_not_reached();
416                 bytes_to_read = 0;
417         }
418         bytes_read = file_read(&hdr, 1, bytes_to_read, wth->fh);
419         if (bytes_read != bytes_to_read) {
420                 *err = file_error(wth->fh);
421                 if (*err != 0)
422                         return -1;
423                 if (bytes_read != 0) {
424                         *err = WTAP_ERR_SHORT_READ;
425                         return -1;
426                 }
427                 return 0;
428         }
429         wth->data_offset += bytes_read;
430
431         adjust_header(wth, &hdr.hdr);
432
433         packet_size = hdr.hdr.incl_len;
434         if (packet_size > WTAP_MAX_PACKET_SIZE) {
435                 /*
436                  * Probably a corrupt capture file; don't blow up trying
437                  * to allocate space for an immensely-large packet.
438                  */
439                 g_message("pcap: File has %u-byte packet, bigger than maximum of %u",
440                     packet_size, WTAP_MAX_PACKET_SIZE);
441                 *err = WTAP_ERR_BAD_RECORD;
442                 return -1;
443         }
444
445         buffer_assure_space(wth->frame_buffer, packet_size);
446         data_offset = wth->data_offset;
447         errno = WTAP_ERR_CANT_READ;
448         bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
449                         packet_size, wth->fh);
450
451         if (bytes_read != packet_size) {
452                 *err = file_error(wth->fh);
453                 if (*err == 0)
454                         *err = WTAP_ERR_SHORT_READ;
455                 return -1;
456         }
457         wth->data_offset += packet_size;
458
459         wth->phdr.ts.tv_sec = hdr.hdr.ts_sec;
460         wth->phdr.ts.tv_usec = hdr.hdr.ts_usec;
461         wth->phdr.caplen = packet_size;
462         wth->phdr.len = hdr.hdr.orig_len;
463         wth->phdr.pkt_encap = wth->file_encap;
464
465         return data_offset;
466 }
467
468 static void
469 adjust_header(wtap *wth, struct pcaprec_hdr *hdr)
470 {
471         if (wth->capture.pcap->byte_swapped) {
472                 /* Byte-swap the record header fields. */
473                 hdr->ts_sec = BSWAP32(hdr->ts_sec);
474                 hdr->ts_usec = BSWAP32(hdr->ts_usec);
475                 hdr->incl_len = BSWAP32(hdr->incl_len);
476                 hdr->orig_len = BSWAP32(hdr->orig_len);
477         }
478
479         /* In file format version 2.3, the "incl_len" and "orig_len" fields
480            were swapped, in order to match the BPF header layout.
481
482            Unfortunately, some files were, according to a comment in the
483            "libpcap" source, written with version 2.3 in their headers
484            but without the interchanged fields, so if "incl_len" is
485            greater than "orig_len" - which would make no sense - we
486            assume that we need to swap them.  */
487         if (wth->capture.pcap->version_major == 2 &&
488             (wth->capture.pcap->version_minor < 3 ||
489              (wth->capture.pcap->version_minor == 3 &&
490               hdr->incl_len > hdr->orig_len))) {
491                 guint32 temp;
492
493                 temp = hdr->orig_len;
494                 hdr->orig_len = hdr->incl_len;
495                 hdr->incl_len = temp;
496         }
497 }
498
499 static void
500 libpcap_close(wtap *wth)
501 {
502         g_free(wth->capture.pcap);
503 }
504
505 int wtap_pcap_encap_to_wtap_encap(int encap)
506 {
507         if (encap < 0 || encap >= NUM_PCAP_ENCAPS)
508                 return WTAP_ENCAP_UNKNOWN;
509         return pcap_encap[encap];
510 }
511
512 static const int wtap_encap[] = {
513         -1,             /* WTAP_ENCAP_UNKNOWN -> unsupported */
514         1,              /* WTAP_ENCAP_ETHERNET -> DLT_EN10MB */
515         6,              /* WTAP_ENCAP_TR -> DLT_IEEE802 */
516         8,              /* WTAP_ENCAP_SLIP -> DLT_SLIP */
517         9,              /* WTAP_ENCAP_PPP -> DLT_PPP */
518         10,             /* WTAP_ENCAP_FDDI -> DLT_FDDI */
519         10,             /* WTAP_ENCAP_FDDI_BITSWAPPED -> DLT_FDDI */
520         12,             /* WTAP_ENCAP_RAW_IP -> DLT_RAW */
521         7,              /* WTAP_ENCAP_ARCNET -> DLT_ARCNET */
522         11,             /* WTAP_ENCAP_ATM_RFC1483 -> DLT_ATM_RFC1483 */
523         19,             /* WTAP_ENCAP_LINUX_ATM_CLIP */
524         -1,             /* WTAP_ENCAP_LAPB -> unsupported*/
525         -1,             /* WTAP_ENCAP_ATM_SNIFFER -> unsupported */
526         0               /* WTAP_ENCAP_NULL -> DLT_NULL */
527 };
528 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
529
530 /* Returns 0 if we could write the specified encapsulation type,
531    an error indication otherwise. */
532 int libpcap_dump_can_write_encap(int filetype, int encap)
533 {
534         /* Per-packet encapsulations aren't supported. */
535         if (encap == WTAP_ENCAP_PER_PACKET)
536                 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
537
538         if (encap < 0 || encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
539                 return WTAP_ERR_UNSUPPORTED_ENCAP;
540
541         return 0;
542 }
543
544 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
545    failure */
546 gboolean libpcap_dump_open(wtap_dumper *wdh, int *err)
547 {
548         guint32 magic;
549         struct pcap_hdr file_hdr;
550         int nwritten;
551
552         /* This is a libpcap file */
553         wdh->subtype_write = libpcap_dump;
554         wdh->subtype_close = NULL;
555
556         /* Write the file header. */
557         switch (wdh->file_type) {
558
559         case WTAP_FILE_PCAP:
560         case WTAP_FILE_PCAP_SS990417:   /* modified, but with the old magic, sigh */
561                 magic = PCAP_MAGIC;
562                 break;
563
564         case WTAP_FILE_PCAP_SS990915:   /* new magic, extra crap */
565         case WTAP_FILE_PCAP_SS991029:
566                 magic = PCAP_MODIFIED_MAGIC;
567                 break;
568
569         default:
570                 /* We should never get here - our open routine
571                    should only get called for the types above. */
572                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
573                 return FALSE;
574         }
575
576         nwritten = fwrite(&magic, 1, sizeof magic, wdh->fh);
577         if (nwritten != sizeof magic) {
578                 if (nwritten < 0)
579                         *err = errno;
580                 else
581                         *err = WTAP_ERR_SHORT_WRITE;
582                 return FALSE;
583         }
584
585         /* current "libpcap" format is 2.4 */
586         file_hdr.version_major = 2;
587         file_hdr.version_minor = 4;
588         file_hdr.thiszone = 0;  /* XXX - current offset? */
589         file_hdr.sigfigs = 0;   /* unknown, but also apparently unused */
590         file_hdr.snaplen = wdh->snaplen;
591         file_hdr.network = wtap_encap[wdh->encap];
592         nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
593         if (nwritten != sizeof file_hdr) {
594                 if (nwritten < 0)
595                         *err = errno;
596                 else
597                         *err = WTAP_ERR_SHORT_WRITE;
598                 return FALSE;
599         }
600
601         return TRUE;
602 }
603
604 /* Write a record for a packet to a dump file.
605    Returns TRUE on success, FALSE on failure. */
606 static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
607     const union wtap_pseudo_header *pseudo_header, const u_char *pd, int *err)
608 {
609         struct pcaprec_ss990915_hdr rec_hdr;
610         int hdr_size;
611         int nwritten;
612
613         rec_hdr.hdr.ts_sec = phdr->ts.tv_sec;
614         rec_hdr.hdr.ts_usec = phdr->ts.tv_usec;
615         rec_hdr.hdr.incl_len = phdr->caplen;
616         rec_hdr.hdr.orig_len = phdr->len;
617         switch (wdh->file_type) {
618
619         case WTAP_FILE_PCAP:
620                 hdr_size = sizeof (struct pcaprec_hdr);
621                 break;
622
623         case WTAP_FILE_PCAP_SS990417:   /* modified, but with the old magic, sigh */
624         case WTAP_FILE_PCAP_SS991029:
625                 /* XXX - what should we supply here?
626
627                    Alexey's "libpcap" looks up the interface in the system's
628                    interface list if "ifindex" is non-zero, and prints
629                    the interface name.  It ignores "protocol", and uses
630                    "pkt_type" to tag the packet as "host", "broadcast",
631                    "multicast", "other host", "outgoing", or "none of the
632                    above", but that's it.
633
634                    If the capture we're writing isn't a modified or
635                    RH 6.1 capture, we'd have to do some work to
636                    generate the packet type and interface index - and
637                    we can't generate the interface index unless we
638                    just did the capture ourselves in any case.
639
640                    I'm inclined to continue to punt; systems other than
641                    those with the older patch can read standard "libpcap"
642                    files, and systems with the older patch, e.g. RH 6.1,
643                    will just have to live with this. */
644                 rec_hdr.ifindex = 0;
645                 rec_hdr.protocol = 0;
646                 rec_hdr.pkt_type = 0;
647                 hdr_size = sizeof (struct pcaprec_modified_hdr);
648                 break;
649
650         case WTAP_FILE_PCAP_SS990915:   /* new magic, extra crap at the end */
651                 rec_hdr.ifindex = 0;
652                 rec_hdr.protocol = 0;
653                 rec_hdr.pkt_type = 0;
654                 rec_hdr.cpu1 = 0;
655                 rec_hdr.cpu2 = 0;
656                 hdr_size = sizeof (struct pcaprec_ss990915_hdr);
657                 break;
658
659         default:
660                 /* We should never get here - our open routine
661                    should only get called for the types above. */
662                 g_assert_not_reached();
663                 *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
664                 return FALSE;
665         }
666
667         nwritten = fwrite(&rec_hdr, 1, hdr_size, wdh->fh);
668         if (nwritten != hdr_size) {
669                 if (nwritten < 0)
670                         *err = errno;
671                 else
672                         *err = WTAP_ERR_SHORT_WRITE;
673                 return FALSE;
674         }
675         nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
676         if (nwritten != phdr->caplen) {
677                 if (nwritten < 0)
678                         *err = errno;
679                 else
680                         *err = WTAP_ERR_SHORT_WRITE;
681                 return FALSE;
682         }
683         return TRUE;
684 }