Coverage Report

Created: 2026-10-17 08:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpcap/sf-pcap.c
Line
Count
Source
1
/*
2
 * Copyright (c) 1993, 1994, 1995, 1996, 1997
3
 *  The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that: (1) source code distributions
7
 * retain the above copyright notice and this paragraph in its entirety, (2)
8
 * distributions including binary code include the above copyright notice and
9
 * this paragraph in its entirety in the documentation or other materials
10
 * provided with the distribution, and (3) all advertising materials mentioning
11
 * features or use of this software display the following acknowledgement:
12
 * ``This product includes software developed by the University of California,
13
 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14
 * the University nor the names of its contributors may be used to endorse
15
 * or promote products derived from this software without specific prior
16
 * written permission.
17
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20
 *
21
 * sf-pcap.c - libpcap-file-format-specific code from savefile.c
22
 *  Extraction/creation by Jeffrey Mogul, DECWRL
23
 *  Modified by Steve McCanne, LBL.
24
 *
25
 * Used to save the received packet headers, after filtering, to
26
 * a file, and then read them later.
27
 * The first record in the file contains saved values for the machine
28
 * dependent values so we can print the dump file on any architecture.
29
 */
30
31
#include <config.h>
32
33
#include <pcap-types.h>
34
#ifdef _WIN32
35
#include <io.h>
36
#include <fcntl.h>
37
#endif /* _WIN32 */
38
39
#include <errno.h>
40
#include <memory.h>
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <limits.h> /* for INT_MAX */
45
46
#include "pcap-int.h"
47
#include "pcap-util.h"
48
49
#include "pcap-common.h"
50
51
#ifdef HAVE_OS_PROTO_H
52
#include "os-proto.h"
53
#endif
54
55
#include "sf-pcap.h"
56
57
/*
58
 * Setting O_BINARY on Windows is a bit tricky.
59
 */
60
#if defined(_WIN32)
61
  #define SET_BINMODE(f)  _setmode(_fileno(f), _O_BINARY)
62
#endif
63
64
/*
65
 * Standard libpcap format.
66
 *
67
 * The same value is used in the rpcap protocol as an indication of
68
 * the server byte order, to let the client know whether it needs to
69
 * byte-swap some host-byte-order metadata.
70
 */
71
21.2k
#define TCPDUMP_MAGIC   0xa1b2c3d4
72
73
/*
74
 * Alexey Kuznetzov's modified libpcap format.
75
 */
76
22.2k
#define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
77
78
/*
79
 * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt>
80
 * for another modified format.
81
 */
82
#define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd
83
84
/*
85
 * Navtel Communications' format, with nanosecond timestamps,
86
 * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
87
 */
88
0
#define NAVTEL_TCPDUMP_MAGIC  0xa12b3c4d
89
90
/*
91
 * Normal libpcap format, except for seconds/nanoseconds timestamps,
92
 * as per a request by Ulf Lamping <ulf.lamping@web.de>
93
 */
94
11.5k
#define NSEC_TCPDUMP_MAGIC  0xa1b23c4d
95
96
/*
97
 * Used for identification of cbpf-savefile(5).
98
 */
99
#define CBPF_SAVEFILE_MAGIC 0xa1b2c3cb
100
101
/*
102
 * This is a timeval as stored in a savefile.
103
 * It has to use the same types everywhere, independent of the actual
104
 * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some
105
 * platforms and 64-bit tv_sec values on other platforms, and writing
106
 * out native `struct timeval' values would mean files could only be
107
 * read on systems with the same tv_sec size as the system on which
108
 * the file was written.
109
 *
110
 * The fields are unsigned, as that's what the pcap draft specification
111
 * says they are.  (That gives pcap a 68-year Y2.038K reprieve, although
112
 * in 2106 it runs out for good.  pcapng doesn't have that problem,
113
 * unless you pick a *really* high time stamp precision.)
114
 */
115
116
struct pcap_timeval {
117
  bpf_u_int32 tv_sec; /* seconds */
118
  bpf_u_int32 tv_usec;  /* microseconds */
119
};
120
121
/*
122
 * This is a `pcap_pkthdr' as actually stored in a savefile.
123
 *
124
 * Do not change the format of this structure, in any way (this includes
125
 * changes that only affect the length of fields in this structure),
126
 * and do not make the time stamp anything other than seconds and
127
 * microseconds (e.g., seconds and nanoseconds).  Instead:
128
 *
129
 *  introduce a new structure for the new format;
130
 *
131
 *  send mail to "tcpdump-workers@lists.tcpdump.org", requesting
132
 *  a new magic number for your new capture file format, and, when
133
 *  you get the new magic number, put it in "savefile.c";
134
 *
135
 *  use that magic number for save files with the changed record
136
 *  header;
137
 *
138
 *  make the code in "savefile.c" capable of reading files with
139
 *  the old record header as well as files with the new record header
140
 *  (using the magic number to determine the header format).
141
 *
142
 * Then supply the changes by forking the branch at
143
 *
144
 *  https://github.com/the-tcpdump-group/libpcap/tree/master
145
 *
146
 * and issuing a pull request, so that future versions of libpcap and
147
 * programs that use it (such as tcpdump) will be able to read your new
148
 * capture file format.
149
 */
150
151
struct pcap_sf_pkthdr {
152
  struct pcap_timeval ts; /* time stamp */
153
  bpf_u_int32 caplen; /* length of portion present */
154
  bpf_u_int32 len;  /* length of this packet (off wire) */
155
};
156
157
/*
158
 * How a `pcap_pkthdr' is actually stored in savefiles written
159
 * by some patched versions of libpcap (e.g. the ones in Red
160
 * Hat Linux 6.1 and 6.2).
161
 *
162
 * Do not change the format of this structure, in any way (this includes
163
 * changes that only affect the length of fields in this structure).
164
 * Instead, introduce a new structure, as per the above.
165
 */
166
167
struct pcap_sf_patched_pkthdr {
168
  struct pcap_timeval ts; /* time stamp */
169
  bpf_u_int32 caplen; /* length of portion present */
170
  bpf_u_int32 len;  /* length of this packet (off wire) */
171
  int index;
172
  unsigned short protocol;
173
  unsigned char pkt_type;
174
};
175
176
static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
177
178
#ifdef _WIN32
179
/*
180
 * This isn't exported on Windows, because it would only work if both
181
 * libpcap and the code using it were using the same C runtime; otherwise they
182
 * would be using different definitions of a FILE structure.
183
 *
184
 * Instead we define this as a macro in pcap/pcap.h that wraps the hopen
185
 * version that we do export, passing it a raw OS HANDLE, as defined by the
186
 * Win32 / Win64 ABI, obtained from the _fileno() and _get_osfhandle()
187
 * functions of the appropriate CRT.
188
 */
189
static pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *f);
190
#endif /* _WIN32 */
191
192
/*
193
 * Private data for reading pcap savefiles.
194
 */
195
typedef enum {
196
  NOT_SWAPPED,
197
  SWAPPED,
198
  MAYBE_SWAPPED
199
} swapped_type_t;
200
201
typedef enum {
202
  PASS_THROUGH,
203
  SCALE_UP,
204
  SCALE_DOWN
205
} tstamp_scale_type_t;
206
207
struct pcap_sf {
208
  size_t hdrsize;
209
  swapped_type_t lengths_swapped;
210
  tstamp_scale_type_t scale_type;
211
};
212
213
/*
214
 * Check whether this is a pcap savefile and, if it is, extract the
215
 * relevant information from the header.
216
 */
217
pcap_t *
218
pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
219
      int *err)
220
5.74k
{
221
5.74k
  bpf_u_int32 magic_int;
222
5.74k
  struct pcap_file_header hdr;
223
5.74k
  size_t amt_read;
224
5.74k
  pcap_t *p;
225
5.74k
  int swapped = 0;
226
5.74k
  struct pcap_sf *ps;
227
228
  /*
229
   * Assume no read errors.
230
   */
231
5.74k
  *err = 0;
232
233
  /*
234
   * Check whether the first 4 bytes of the file are the magic
235
   * number for a pcap savefile, or for a byte-swapped pcap
236
   * savefile.
237
   */
238
5.74k
  memcpy(&magic_int, magic, sizeof(magic_int));
239
5.74k
  if (magic_int != TCPDUMP_MAGIC &&
240
4.98k
      magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
241
4.93k
      magic_int != NSEC_TCPDUMP_MAGIC) {
242
4.89k
    magic_int = PCAP_BSWAP_32(magic_int);
243
4.89k
    if (magic_int != TCPDUMP_MAGIC &&
244
2.52k
        magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
245
2.48k
        magic_int != NSEC_TCPDUMP_MAGIC)
246
1.53k
      return (NULL);  /* nope */
247
3.35k
    swapped = 1;
248
3.35k
  }
249
250
  /*
251
   * They are.  Put the magic number in the header, and read
252
   * the rest of the header.
253
   */
254
4.20k
  hdr.magic = magic_int;
255
4.20k
  amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
256
4.20k
      sizeof(hdr) - sizeof(hdr.magic), fp);
257
4.20k
  if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
258
0
    if (ferror(fp)) {
259
0
      pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
260
0
          errno, "error reading dump file");
261
0
    } else {
262
0
      snprintf(errbuf, PCAP_ERRBUF_SIZE,
263
0
          "truncated dump file; tried to read %zu file header bytes, only got %zu",
264
0
          sizeof(hdr), amt_read);
265
0
    }
266
0
    *err = 1;
267
0
    return (NULL);
268
0
  }
269
270
  /*
271
   * If it's a byte-swapped capture file, byte-swap the header.
272
   */
273
4.20k
  if (swapped) {
274
3.35k
    hdr.version_major = PCAP_BSWAP_16(hdr.version_major);
275
3.35k
    hdr.version_minor = PCAP_BSWAP_16(hdr.version_minor);
276
3.35k
    hdr.thiszone = PCAP_BSWAP_32(hdr.thiszone);
277
3.35k
    hdr.sigfigs = PCAP_BSWAP_32(hdr.sigfigs);
278
3.35k
    hdr.snaplen = PCAP_BSWAP_32(hdr.snaplen);
279
3.35k
    hdr.linktype = PCAP_BSWAP_32(hdr.linktype);
280
3.35k
  }
281
282
  /*
283
   * currently only versions 2.[0-4] are supported with
284
   * the exception of 543.0 for DG/UX tcpdump.
285
   */
286
4.20k
  if (! ((hdr.version_major == PCAP_VERSION_MAJOR &&
287
3.43k
    hdr.version_minor <= PCAP_VERSION_MINOR) ||
288
785
         (hdr.version_major == 543 &&
289
743
    hdr.version_minor == 0))) {
290
58
    snprintf(errbuf, PCAP_ERRBUF_SIZE,
291
58
       "unsupported pcap savefile version %u.%u",
292
58
       hdr.version_major, hdr.version_minor);
293
58
    *err = 1;
294
58
    return NULL;
295
58
  }
296
297
  /*
298
   * Check the main reserved field.
299
   */
300
4.15k
  if (LT_RESERVED1(hdr.linktype) != 0) {
301
11
    snprintf(errbuf, PCAP_ERRBUF_SIZE,
302
11
       "savefile linktype reserved field not zero (0x%08x)",
303
11
       LT_RESERVED1(hdr.linktype));
304
11
    *err = 1;
305
11
    return NULL;
306
11
  }
307
308
  /*
309
   * OK, this is a good pcap file.
310
   * Allocate a pcap_t for it.
311
   */
312
4.13k
  p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_sf);
313
4.13k
  if (p == NULL) {
314
    /* Allocation failed. */
315
0
    *err = 1;
316
0
    return (NULL);
317
0
  }
318
4.13k
  p->swapped = swapped;
319
4.13k
  p->version_major = hdr.version_major;
320
4.13k
  p->version_minor = hdr.version_minor;
321
4.13k
  p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
322
4.13k
  p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
323
4.13k
  p->snapshot = pcapint_adjust_snapshot(p->linktype, hdr.snaplen);
324
325
4.13k
  p->next_packet_op = pcap_next_packet;
326
327
4.13k
  ps = p->priv;
328
329
4.13k
  p->opt.tstamp_precision = precision;
330
331
  /*
332
   * Will we need to scale the timestamps to match what the
333
   * user wants?
334
   */
335
4.13k
  switch (precision) {
336
337
4.13k
  case PCAP_TSTAMP_PRECISION_MICRO:
338
4.13k
    if (magic_int == NSEC_TCPDUMP_MAGIC) {
339
      /*
340
       * The file has nanoseconds, the user
341
       * wants microseconds; scale the
342
       * precision down.
343
       */
344
967
      ps->scale_type = SCALE_DOWN;
345
3.17k
    } else {
346
      /*
347
       * The file has microseconds, the
348
       * user wants microseconds; nothing to do.
349
       */
350
3.17k
      ps->scale_type = PASS_THROUGH;
351
3.17k
    }
352
4.13k
    break;
353
354
0
  case PCAP_TSTAMP_PRECISION_NANO:
355
0
    if (magic_int == NSEC_TCPDUMP_MAGIC) {
356
      /*
357
       * The file has nanoseconds, the
358
       * user wants nanoseconds; nothing to do.
359
       */
360
0
      ps->scale_type = PASS_THROUGH;
361
0
    } else {
362
      /*
363
       * The file has microseconds, the user
364
       * wants nanoseconds; scale the
365
       * precision up.
366
       */
367
0
      ps->scale_type = SCALE_UP;
368
0
    }
369
0
    break;
370
371
0
  default:
372
0
    snprintf(errbuf, PCAP_ERRBUF_SIZE,
373
0
        "unknown time stamp resolution %u", precision);
374
0
    free(p);
375
0
    *err = 1;
376
0
    return (NULL);
377
4.13k
  }
378
379
  /*
380
   * We interchanged the caplen and len fields at version 2.3,
381
   * in order to match the bpf header layout.  But unfortunately
382
   * some files were written with version 2.3 in their headers
383
   * but without the interchanged fields.
384
   *
385
   * In addition, DG/UX tcpdump writes out files with a version
386
   * number of 543.0, and with the caplen and len fields in the
387
   * pre-2.3 order.
388
   */
389
4.13k
  switch (hdr.version_major) {
390
391
3.41k
  case 2:
392
3.41k
    if (hdr.version_minor < 3)
393
1.34k
      ps->lengths_swapped = SWAPPED;
394
2.07k
    else if (hdr.version_minor == 3)
395
1.44k
      ps->lengths_swapped = MAYBE_SWAPPED;
396
625
    else
397
625
      ps->lengths_swapped = NOT_SWAPPED;
398
3.41k
    break;
399
400
726
  case 543:
401
726
    ps->lengths_swapped = SWAPPED;
402
726
    break;
403
404
0
  default:
405
0
    ps->lengths_swapped = NOT_SWAPPED;
406
0
    break;
407
4.13k
  }
408
409
4.13k
  if (magic_int == KUZNETZOV_TCPDUMP_MAGIC) {
410
    /*
411
     * XXX - the patch that's in some versions of libpcap
412
     * changes the packet header but not the magic number,
413
     * and some other versions with this magic number have
414
     * some extra debugging information in the packet header;
415
     * we'd have to use some hacks^H^H^H^H^Hheuristics to
416
     * detect those variants.
417
     *
418
     * Wireshark does that, but it does so by trying to read
419
     * the first two packets of the file with each of the
420
     * record header formats.  That currently means it seeks
421
     * backwards and retries the reads, which doesn't work
422
     * on pipes.  We want to be able to read from a pipe, so
423
     * that strategy won't work; we'd have to buffer some
424
     * data ourselves and read from that buffer in order to
425
     * make that work.
426
     */
427
88
    ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
428
429
88
    if (p->linktype == DLT_EN10MB) {
430
      /*
431
       * This capture might have been done in raw mode
432
       * or cooked mode.
433
       *
434
       * If it was done in cooked mode, p->snapshot was
435
       * passed to recvfrom() as the buffer size, meaning
436
       * that the most packet data that would be copied
437
       * would be p->snapshot.  However, a faked Ethernet
438
       * header would then have been added to it, so the
439
       * most data that would be in a packet in the file
440
       * would be p->snapshot + 14.
441
       *
442
       * We can't easily tell whether the capture was done
443
       * in raw mode or cooked mode, so we'll assume it was
444
       * cooked mode, and add 14 to the snapshot length.
445
       * That means that, for a raw capture, the snapshot
446
       * length will be misleading if you use it to figure
447
       * out why a capture doesn't have all the packet data,
448
       * but there's not much we can do to avoid that.
449
       *
450
       * But don't grow the snapshot length past the
451
       * maximum value of an int.
452
       */
453
61
      if (p->snapshot <= INT_MAX - 14)
454
59
        p->snapshot += 14;
455
2
      else
456
2
        p->snapshot = INT_MAX;
457
61
    }
458
88
  } else
459
4.05k
    ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
460
461
  /*
462
   * Allocate a buffer for the packet data.
463
   * Choose the minimum of the file's snapshot length and 2K bytes;
464
   * that should be enough for most network packets - we'll grow it
465
   * if necessary.  That way, we don't allocate a huge chunk of
466
   * memory just because there's a huge snapshot length, as the
467
   * snapshot length might be larger than the size of the largest
468
   * packet.
469
   */
470
4.13k
  p->bufsize = p->snapshot;
471
4.13k
  if (p->bufsize > 2048)
472
3.85k
    p->bufsize = 2048;
473
4.13k
  p->buffer = malloc(p->bufsize);
474
4.13k
  if (p->buffer == NULL) {
475
0
    snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
476
0
    free(p);
477
0
    *err = 1;
478
0
    return (NULL);
479
0
  }
480
481
4.13k
  p->cleanup_op = pcapint_sf_cleanup;
482
483
4.13k
  return (p);
484
4.13k
}
485
486
/*
487
 * Read and return the next packet from the savefile.  Return the header
488
 * in hdr and a pointer to the contents in data.  Return 1 on success, 0
489
 * if there were no more packets, and -1 on an error.
490
 */
491
static int
492
pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
493
43.8k
{
494
43.8k
  struct pcap_sf *ps = p->priv;
495
43.8k
  struct pcap_sf_patched_pkthdr sf_hdr;
496
43.8k
  FILE *fp = p->rfile;
497
43.8k
  size_t amt_read;
498
43.8k
  bpf_u_int32 t;
499
500
  /*
501
   * Read the packet header; the structure we use as a buffer
502
   * is the longer structure for files generated by the patched
503
   * libpcap, but if the file has the magic number for an
504
   * unpatched libpcap we only read as many bytes as the regular
505
   * header has.
506
   */
507
43.8k
  amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
508
43.8k
  if (amt_read != ps->hdrsize) {
509
3.82k
    if (ferror(fp)) {
510
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
511
0
          errno, "error reading dump file");
512
0
      return (-1);
513
3.82k
    } else {
514
3.82k
      if (amt_read != 0) {
515
154
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
516
154
            "truncated dump file; tried to read %zu header bytes, only got %zu",
517
154
            ps->hdrsize, amt_read);
518
154
        return (-1);
519
154
      }
520
      /* EOF */
521
3.66k
      return (0);
522
3.82k
    }
523
3.82k
  }
524
525
40.0k
  if (p->swapped) {
526
    /* these were written in opposite byte order */
527
30.0k
    hdr->caplen = PCAP_BSWAP_32(sf_hdr.caplen);
528
30.0k
    hdr->len = PCAP_BSWAP_32(sf_hdr.len);
529
30.0k
    hdr->ts.tv_sec = PCAP_BSWAP_32(sf_hdr.ts.tv_sec);
530
30.0k
    hdr->ts.tv_usec = PCAP_BSWAP_32(sf_hdr.ts.tv_usec);
531
30.0k
  } else {
532
10.0k
    hdr->caplen = sf_hdr.caplen;
533
10.0k
    hdr->len = sf_hdr.len;
534
10.0k
    hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
535
10.0k
    hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
536
10.0k
  }
537
538
40.0k
  switch (ps->scale_type) {
539
540
29.7k
  case PASS_THROUGH:
541
    /*
542
     * Just pass the time stamp through.
543
     */
544
29.7k
    break;
545
546
0
  case SCALE_UP:
547
    /*
548
     * File has microseconds, user wants nanoseconds; convert
549
     * it.
550
     */
551
0
    hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
552
0
    break;
553
554
10.2k
  case SCALE_DOWN:
555
    /*
556
     * File has nanoseconds, user wants microseconds; convert
557
     * it.
558
     */
559
10.2k
    hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
560
10.2k
    break;
561
40.0k
  }
562
563
  /* Swap the caplen and len fields, if necessary. */
564
40.0k
  switch (ps->lengths_swapped) {
565
566
5.92k
  case NOT_SWAPPED:
567
5.92k
    break;
568
569
18.2k
  case MAYBE_SWAPPED:
570
18.2k
    if (hdr->caplen <= hdr->len) {
571
      /*
572
       * The captured length is <= the actual length,
573
       * so presumably they weren't swapped.
574
       */
575
10.9k
      break;
576
10.9k
    }
577
    /* FALLTHROUGH */
578
579
23.1k
  case SWAPPED:
580
23.1k
    t = hdr->caplen;
581
23.1k
    hdr->caplen = hdr->len;
582
23.1k
    hdr->len = t;
583
23.1k
    break;
584
40.0k
  }
585
586
  /*
587
   * Is the packet bigger than we consider sane?
588
   */
589
40.0k
  if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) {
590
    /*
591
     * Yes.  This may be a damaged or fuzzed file.
592
     *
593
     * Is it bigger than the snapshot length?
594
     * (We don't treat that as an error if it's not
595
     * bigger than the maximum we consider sane; see
596
     * below.)
597
     */
598
97
    if (hdr->caplen > (bpf_u_int32)p->snapshot) {
599
78
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
600
78
          "invalid packet capture length %u, bigger than "
601
78
          "snaplen of %d", hdr->caplen, p->snapshot);
602
78
    } else {
603
19
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
604
19
          "invalid packet capture length %u, bigger than "
605
19
          "maximum of %u", hdr->caplen,
606
19
          max_snaplen_for_dlt(p->linktype));
607
19
    }
608
97
    return (-1);
609
97
  }
610
611
39.9k
  if (hdr->caplen > (bpf_u_int32)p->snapshot) {
612
    /*
613
     * The packet is bigger than the snapshot length
614
     * for this file.
615
     *
616
     * This can happen due to Solaris 2.3 systems tripping
617
     * over the BUFMOD problem and not setting the snapshot
618
     * length correctly in the savefile header.
619
     *
620
     * libpcap 0.4 and later on Solaris 2.3 should set the
621
     * snapshot length correctly in the pcap file header,
622
     * even though they don't set a snapshot length in bufmod
623
     * (the buggy bufmod chops off the *beginning* of the
624
     * packet if a snapshot length is specified); they should
625
     * also reduce the captured length, as supplied to the
626
     * per-packet callback, to the snapshot length if it's
627
     * greater than the snapshot length, so the code using
628
     * libpcap should see the packet cut off at the snapshot
629
     * length, even though the full packet is copied up to
630
     * userland.
631
     *
632
     * However, perhaps some versions of libpcap failed to
633
     * set the snapshot length correctly in the file header
634
     * or the per-packet header, or perhaps this is a
635
     * corrupted savefile or a savefile built/modified by a
636
     * fuzz tester, so we check anyway.  We grow the buffer
637
     * to be big enough for the snapshot length, read up
638
     * to the snapshot length, discard the rest of the
639
     * packet, and report the snapshot length as the captured
640
     * length; we don't want to hand our caller a packet
641
     * bigger than the snapshot length, because they might
642
     * be assuming they'll never be handed such a packet,
643
     * and might copy the packet into a snapshot-length-
644
     * sized buffer, assuming it'll fit.
645
     */
646
2.55k
    size_t bytes_to_discard;
647
2.55k
    size_t bytes_to_read, bytes_read;
648
2.55k
    char discard_buf[4096];
649
650
2.55k
    if (hdr->caplen > p->bufsize) {
651
      /*
652
       * Grow the buffer to the snapshot length.
653
       */
654
2.55k
      if (!pcapint_grow_buffer(p, p->snapshot, p->errbuf))
655
0
        return (-1);
656
2.55k
    }
657
658
    /*
659
     * Read the first p->snapshot bytes into the buffer.
660
     */
661
2.55k
    amt_read = fread(p->buffer, 1, p->snapshot, fp);
662
2.55k
    if (amt_read != (bpf_u_int32)p->snapshot) {
663
56
      if (ferror(fp)) {
664
0
        pcapint_fmt_errmsg_for_errno(p->errbuf,
665
0
             PCAP_ERRBUF_SIZE, errno,
666
0
            "error reading dump file");
667
56
      } else {
668
        /*
669
         * Yes, this uses hdr->caplen; technically,
670
         * it's true, because we would try to read
671
         * and discard the rest of those bytes, and
672
         * that would fail because we got EOF before
673
         * the read finished.
674
         */
675
56
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
676
56
            "truncated dump file; tried to read %d captured bytes, only got %zu",
677
56
            p->snapshot, amt_read);
678
56
      }
679
56
      return (-1);
680
56
    }
681
682
    /*
683
     * Now read and discard what's left.
684
     */
685
2.50k
    bytes_to_discard = hdr->caplen - p->snapshot;
686
2.50k
    bytes_read = amt_read;
687
5.41k
    while (bytes_to_discard != 0) {
688
2.97k
      bytes_to_read = bytes_to_discard;
689
2.97k
      if (bytes_to_read > sizeof (discard_buf))
690
502
        bytes_to_read = sizeof (discard_buf);
691
2.97k
      amt_read = fread(discard_buf, 1, bytes_to_read, fp);
692
2.97k
      bytes_read += amt_read;
693
2.97k
      if (amt_read != bytes_to_read) {
694
57
        if (ferror(fp)) {
695
0
          pcapint_fmt_errmsg_for_errno(p->errbuf,
696
0
              PCAP_ERRBUF_SIZE, errno,
697
0
              "error reading dump file");
698
57
        } else {
699
57
          snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
700
57
              "truncated dump file; tried to read %u captured bytes, only got %zu",
701
57
              hdr->caplen, bytes_read);
702
57
        }
703
57
        return (-1);
704
57
      }
705
2.91k
      bytes_to_discard -= amt_read;
706
2.91k
    }
707
708
    /*
709
     * Adjust caplen accordingly, so we don't get confused later
710
     * as to how many bytes we have to play with.
711
     */
712
2.44k
    hdr->caplen = p->snapshot;
713
37.3k
  } else {
714
    /*
715
     * The packet is within the snapshot length for this file.
716
     */
717
37.3k
    if (hdr->caplen > p->bufsize) {
718
      /*
719
       * Grow the buffer to the next power of 2, or
720
       * the snaplen, whichever is lower.
721
       */
722
456
      u_int new_bufsize;
723
724
456
      new_bufsize = hdr->caplen;
725
      /*
726
       * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
727
       */
728
456
      new_bufsize--;
729
456
      new_bufsize |= new_bufsize >> 1;
730
456
      new_bufsize |= new_bufsize >> 2;
731
456
      new_bufsize |= new_bufsize >> 4;
732
456
      new_bufsize |= new_bufsize >> 8;
733
456
      new_bufsize |= new_bufsize >> 16;
734
456
      new_bufsize++;
735
736
456
      if (new_bufsize > (u_int)p->snapshot)
737
34
        new_bufsize = p->snapshot;
738
739
456
      if (!pcapint_grow_buffer(p, new_bufsize, p->errbuf))
740
0
        return (-1);
741
456
    }
742
743
    /* read the packet itself */
744
37.3k
    amt_read = fread(p->buffer, 1, hdr->caplen, fp);
745
37.3k
    if (amt_read != hdr->caplen) {
746
108
      if (ferror(fp)) {
747
0
        pcapint_fmt_errmsg_for_errno(p->errbuf,
748
0
            PCAP_ERRBUF_SIZE, errno,
749
0
            "error reading dump file");
750
108
      } else {
751
108
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
752
108
            "truncated dump file; tried to read %u captured bytes, only got %zu",
753
108
            hdr->caplen, amt_read);
754
108
      }
755
108
      return (-1);
756
108
    }
757
37.3k
  }
758
39.7k
  *data = p->buffer;
759
760
39.7k
  pcapint_post_process(p->linktype, p->swapped, hdr, *data);
761
762
39.7k
  return (1);
763
39.9k
}
764
765
static int
766
sf_write_header(pcap_t *p, FILE *fp, int linktype, int snaplen)
767
0
{
768
0
  struct pcap_file_header hdr;
769
770
0
  hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
771
0
  hdr.version_major = PCAP_VERSION_MAJOR;
772
0
  hdr.version_minor = PCAP_VERSION_MINOR;
773
774
  /*
775
   * https://www.tcpdump.org/manpages/pcap-savefile.5.txt states:
776
   * thiszone (Reserved1): 4-byte not used - SHOULD be filled with 0
777
   * sigfigs (Reserved2):  4-byte not used - SHOULD be filled with 0
778
   */
779
0
  hdr.thiszone = 0;
780
0
  hdr.sigfigs = 0;
781
0
  hdr.snaplen = snaplen;
782
0
  hdr.linktype = linktype;
783
784
0
  if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
785
0
    return (-1);
786
787
0
  return (0);
788
0
}
789
790
/*
791
 * Output a packet to the initialized dump file.
792
 */
793
void
794
pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
795
0
{
796
0
  FILE *f;
797
0
  struct pcap_sf_pkthdr sf_hdr;
798
799
0
  f = (FILE *)user;
800
  /*
801
   * If the output file handle is in an error state, don't write
802
   * anything.
803
   *
804
   * While in principle a file handle can return from an error state
805
   * to a normal state (for example if a disk that is full has space
806
   * freed), we have possibly left a broken file already, and won't
807
   * be able to clean it up. The safest option is to do nothing.
808
   *
809
   * Note that if we could guarantee that fwrite() was atomic we
810
   * might be able to insure that we don't produce a corrupted file,
811
   * but the standard defines fwrite() as a series of fputc() calls,
812
   * so we really have no insurance that things are not fubared.
813
   *
814
   * http://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html
815
   */
816
0
  if (ferror(f))
817
0
    return;
818
  /*
819
   * Better not try writing pcap files after
820
   * 2106-02-07 06:28:15 UTC; switch to pcapng.
821
   * (And better not try writing pcap files with time stamps
822
   * that predate 1970-01-01 00:00:00 UTC; that's not supported.
823
   * You could try using pcapng with the if_tsoffset field in
824
   * the IDB for the interface(s) with packets with those time
825
   * stamps, but you may also have to get a link-layer type for
826
   * IBM Bisync or whatever link layer even older forms
827
   * of computer communication used.)
828
   */
829
0
  sf_hdr.ts.tv_sec  = (bpf_u_int32)h->ts.tv_sec;
830
0
  sf_hdr.ts.tv_usec = (bpf_u_int32)h->ts.tv_usec;
831
0
  sf_hdr.caplen     = h->caplen;
832
0
  sf_hdr.len        = h->len;
833
  /*
834
   * We only write the packet if we can write the header properly.
835
   *
836
   * This doesn't prevent us from having corrupted output, and if we
837
   * for some reason don't get a complete write we don't have any
838
   * way to set ferror() to prevent future writes from being
839
   * attempted, but it is better than nothing.
840
   */
841
0
  if (fwrite(&sf_hdr, sizeof(sf_hdr), 1, f) == 1) {
842
0
    (void)fwrite(sp, h->caplen, 1, f);
843
0
  }
844
0
}
845
846
static pcap_dumper_t *
847
pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
848
0
{
849
850
#if defined(_WIN32)
851
  /*
852
   * If we're writing to the standard output, put it in binary
853
   * mode, as savefiles are binary files.
854
   *
855
   * Otherwise, we turn off buffering.
856
   * XXX - why?  And why not on the standard output?
857
   */
858
  if (f == stdout)
859
    SET_BINMODE(f);
860
  else
861
    setvbuf(f, NULL, _IONBF, 0);
862
#endif
863
0
  if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
864
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
865
0
        errno, "Can't write to %s", fname);
866
0
    if (f != stdout)
867
0
      (void)fclose(f);
868
0
    return (NULL);
869
0
  }
870
0
  return ((pcap_dumper_t *)f);
871
0
}
872
873
/*
874
 * Initialize so that sf_write() will output to the file named 'fname'.
875
 */
876
pcap_dumper_t *
877
pcap_dump_open(pcap_t *p, const char *fname)
878
0
{
879
0
  FILE *f;
880
0
  int linktype;
881
882
  /*
883
   * If this pcap_t hasn't been activated, it doesn't have a
884
   * link-layer type, so we can't use it.
885
   */
886
0
  if (!p->activated) {
887
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
888
0
        "%s: not-yet-activated pcap_t passed to pcap_dump_open",
889
0
        fname);
890
0
    return (NULL);
891
0
  }
892
0
  linktype = dlt_to_linktype(p->linktype);
893
0
  if (linktype == -1) {
894
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
895
0
        "%s: link-layer type %d isn't supported in savefiles",
896
0
        fname, p->linktype);
897
0
    return (NULL);
898
0
  }
899
0
  linktype |= p->linktype_ext;
900
901
0
  if (fname == NULL) {
902
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
903
0
        "A null pointer was supplied as the file name");
904
0
    return NULL;
905
0
  }
906
0
  if (fname[0] == '-' && fname[1] == '\0') {
907
0
    f = stdout;
908
0
    fname = "standard output";
909
0
  } else {
910
    /*
911
     * "b" is supported as of C90, so *all* UN*Xes should
912
     * support it, even though it does nothing.  It's
913
     * required on Windows, as the file is a binary file
914
     * and must be written in binary mode.
915
     */
916
0
    f = pcapint_charset_fopen(fname, "wb");
917
0
    if (f == NULL) {
918
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
919
0
          errno, "%s", fname);
920
0
      return (NULL);
921
0
    }
922
0
  }
923
0
  return (pcap_setup_dump(p, linktype, f, fname));
924
0
}
925
926
#ifdef _WIN32
927
/*
928
 * Initialize so that sf_write() will output to a stream wrapping the given raw
929
 * OS file HANDLE.
930
 */
931
pcap_dumper_t *
932
pcap_dump_hopen(pcap_t *p, intptr_t osfd)
933
{
934
  int fd;
935
  FILE *file;
936
937
  fd = _open_osfhandle(osfd, _O_APPEND);
938
  if (fd < 0) {
939
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
940
        errno, "_open_osfhandle");
941
    return NULL;
942
  }
943
944
  file = _fdopen(fd, "wb");
945
  if (file == NULL) {
946
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
947
        errno, "_fdopen");
948
    _close(fd);
949
    return NULL;
950
  }
951
952
  return pcap_dump_fopen(p, file);
953
}
954
#endif /* _WIN32 */
955
956
/*
957
 * Initialize so that sf_write() will output to the given stream.
958
 */
959
#ifdef _WIN32
960
static
961
#endif /* _WIN32 */
962
pcap_dumper_t *
963
pcap_dump_fopen(pcap_t *p, FILE *f)
964
0
{
965
0
  int linktype;
966
967
0
  linktype = dlt_to_linktype(p->linktype);
968
0
  if (linktype == -1) {
969
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
970
0
        "stream: link-layer type %d isn't supported in savefiles",
971
0
        p->linktype);
972
0
    return (NULL);
973
0
  }
974
0
  linktype |= p->linktype_ext;
975
976
0
  return (pcap_setup_dump(p, linktype, f, "stream"));
977
0
}
978
979
pcap_dumper_t *
980
pcap_dump_open_append(pcap_t *p, const char *fname)
981
0
{
982
0
  FILE *f;
983
0
  int linktype;
984
0
  size_t amt_read;
985
0
  struct pcap_file_header ph;
986
987
0
  linktype = dlt_to_linktype(p->linktype);
988
0
  if (linktype == -1) {
989
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
990
0
        "%s: link-layer type %d isn't supported in savefiles",
991
0
        fname, linktype);
992
0
    return (NULL);
993
0
  }
994
995
0
  if (fname == NULL) {
996
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
997
0
        "A null pointer was supplied as the file name");
998
0
    return NULL;
999
0
  }
1000
0
  if (fname[0] == '-' && fname[1] == '\0')
1001
0
    return (pcap_setup_dump(p, linktype, stdout, "standard output"));
1002
1003
  /*
1004
   * "a" will cause the file *not* to be truncated if it exists
1005
   * but will cause it to be created if it doesn't.  It will
1006
   * also cause all writes to be done at the end of the file,
1007
   * but will allow reads to be done anywhere in the file.  This
1008
   * is what we need, because we need to read from the beginning
1009
   * of the file to see if it already has a header and packets
1010
   * or if it doesn't.
1011
   *
1012
   * "b" is supported as of C90, so *all* UN*Xes should support it,
1013
   * even though it does nothing.  It's required on Windows, as the
1014
   * file is a binary file and must be read in binary mode.
1015
   */
1016
0
  f = pcapint_charset_fopen(fname, "ab+");
1017
0
  if (f == NULL) {
1018
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1019
0
        errno, "%s", fname);
1020
0
    return (NULL);
1021
0
  }
1022
1023
  /*
1024
   * Try to read a pcap header.
1025
   *
1026
   * We do not assume that the file will be positioned at the
1027
   * beginning immediately after we've opened it - we seek to
1028
   * the beginning.  ISO C says it's implementation-defined
1029
   * whether the file position indicator is at the beginning
1030
   * or the end of the file after an append-mode open, and
1031
   * it wasn't obvious from the Single UNIX Specification
1032
   * or the Microsoft documentation how that works on SUS-
1033
   * compliant systems or on Windows.
1034
   */
1035
0
  if (fseek(f, 0, SEEK_SET) == -1) {
1036
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1037
0
        errno, "Can't seek to the beginning of %s", fname);
1038
0
    (void)fclose(f);
1039
0
    return (NULL);
1040
0
  }
1041
0
  amt_read = fread(&ph, 1, sizeof (ph), f);
1042
0
  if (amt_read != sizeof (ph)) {
1043
0
    if (ferror(f)) {
1044
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1045
0
          errno, "%s", fname);
1046
0
      (void)fclose(f);
1047
0
      return (NULL);
1048
0
    } else if (feof(f) && amt_read > 0) {
1049
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1050
0
          "%s: truncated pcap file header", fname);
1051
0
      (void)fclose(f);
1052
0
      return (NULL);
1053
0
    }
1054
0
  }
1055
1056
#if defined(_WIN32)
1057
  /*
1058
   * We turn off buffering.
1059
   * XXX - why?  And why not on the standard output?
1060
   */
1061
  setvbuf(f, NULL, _IONBF, 0);
1062
#endif
1063
1064
  /*
1065
   * If a header is already present and:
1066
   *
1067
   *  it's not for a pcap file of the appropriate resolution
1068
   *  and the right byte order for this machine;
1069
   *
1070
   *  the link-layer header types don't match;
1071
   *
1072
   *  the snapshot lengths don't match;
1073
   *
1074
   * return an error.
1075
   */
1076
0
  if (amt_read > 0) {
1077
    /*
1078
     * A header is already present.
1079
     * Do the checks.
1080
     */
1081
0
    switch (ph.magic) {
1082
1083
0
    case TCPDUMP_MAGIC:
1084
0
      if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
1085
0
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1086
0
            "%s: different time stamp precision, cannot append to file", fname);
1087
0
        (void)fclose(f);
1088
0
        return (NULL);
1089
0
      }
1090
0
      break;
1091
1092
0
    case NSEC_TCPDUMP_MAGIC:
1093
0
      if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
1094
0
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1095
0
            "%s: different time stamp precision, cannot append to file", fname);
1096
0
        (void)fclose(f);
1097
0
        return (NULL);
1098
0
      }
1099
0
      break;
1100
1101
0
    case PCAP_BSWAP_32(TCPDUMP_MAGIC):
1102
0
    case PCAP_BSWAP_32(NSEC_TCPDUMP_MAGIC):
1103
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1104
0
          "%s: different byte order, cannot append to file", fname);
1105
0
      (void)fclose(f);
1106
0
      return (NULL);
1107
1108
0
    case KUZNETZOV_TCPDUMP_MAGIC:
1109
0
    case PCAP_BSWAP_32(KUZNETZOV_TCPDUMP_MAGIC):
1110
0
    case NAVTEL_TCPDUMP_MAGIC:
1111
0
    case PCAP_BSWAP_32(NAVTEL_TCPDUMP_MAGIC):
1112
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1113
0
          "%s: not a pcap file to which we can append", fname);
1114
0
      (void)fclose(f);
1115
0
      return (NULL);
1116
1117
0
    default:
1118
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1119
0
          "%s: not a pcap file", fname);
1120
0
      (void)fclose(f);
1121
0
      return (NULL);
1122
0
    }
1123
1124
    /*
1125
     * Good version?
1126
     */
1127
0
    if (ph.version_major != PCAP_VERSION_MAJOR ||
1128
0
        ph.version_minor != PCAP_VERSION_MINOR) {
1129
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1130
0
          "%s: version is %u.%u, cannot append to file", fname,
1131
0
          ph.version_major, ph.version_minor);
1132
0
      (void)fclose(f);
1133
0
      return (NULL);
1134
0
    }
1135
0
    if ((bpf_u_int32)linktype != ph.linktype) {
1136
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1137
0
          "%s: different linktype, cannot append to file", fname);
1138
0
      (void)fclose(f);
1139
0
      return (NULL);
1140
0
    }
1141
0
    if ((bpf_u_int32)p->snapshot != ph.snaplen) {
1142
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1143
0
          "%s: different snaplen, cannot append to file", fname);
1144
0
      (void)fclose(f);
1145
0
      return (NULL);
1146
0
    }
1147
0
  } else {
1148
    /*
1149
     * A header isn't present; attempt to write it.
1150
     */
1151
0
    if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
1152
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1153
0
          errno, "Can't write to %s", fname);
1154
0
      (void)fclose(f);
1155
0
      return (NULL);
1156
0
    }
1157
0
  }
1158
1159
  /*
1160
   * Start writing at the end of the file.
1161
   *
1162
   * XXX - this shouldn't be necessary, given that we're opening
1163
   * the file in append mode, and ISO C specifies that all writes
1164
   * are done at the end of the file in that mode.
1165
   */
1166
0
  if (fseek(f, 0, SEEK_END) == -1) {
1167
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1168
0
        errno, "Can't seek to the end of %s", fname);
1169
0
    (void)fclose(f);
1170
0
    return (NULL);
1171
0
  }
1172
0
  return ((pcap_dumper_t *)f);
1173
0
}
1174
1175
FILE *
1176
pcap_dump_file(pcap_dumper_t *p)
1177
0
{
1178
0
  return ((FILE *)p);
1179
0
}
1180
1181
long
1182
pcap_dump_ftell(pcap_dumper_t *p)
1183
0
{
1184
0
  return (ftell((FILE *)p));
1185
0
}
1186
1187
#if defined(HAVE_FSEEKO)
1188
/*
1189
 * We have fseeko(), so we have ftello().
1190
 * If we have large file support (files larger than 2^31-1 bytes),
1191
 * ftello() will give us a current file position with more than 32
1192
 * bits.
1193
 */
1194
int64_t
1195
pcap_dump_ftell64(pcap_dumper_t *p)
1196
0
{
1197
0
  return (ftello((FILE *)p));
1198
0
}
1199
#elif defined(_MSC_VER)
1200
/*
1201
 * We have Visual Studio; we support only 2015 and later, so we have
1202
 * _ftelli64().
1203
 */
1204
int64_t
1205
pcap_dump_ftell64(pcap_dumper_t *p)
1206
{
1207
  return (_ftelli64((FILE *)p));
1208
}
1209
#else
1210
/*
1211
 * We don't have ftello() or _ftelli64(), so fall back on ftell().
1212
 * Either long is 64 bits, in which case ftell() should suffice,
1213
 * or this is probably an older 32-bit UN*X without large file
1214
 * support, which means you'll probably get errors trying to
1215
 * write files > 2^31-1, so it won't matter anyway.
1216
 *
1217
 * XXX - what about MinGW?
1218
 */
1219
int64_t
1220
pcap_dump_ftell64(pcap_dumper_t *p)
1221
{
1222
  return (ftell((FILE *)p));
1223
}
1224
#endif
1225
1226
int
1227
pcap_dump_flush(pcap_dumper_t *p)
1228
0
{
1229
1230
0
  if (fflush((FILE *)p) == EOF)
1231
0
    return (-1);
1232
0
  else
1233
0
    return (0);
1234
0
}
1235
1236
void
1237
pcap_dump_close(pcap_dumper_t *p)
1238
0
{
1239
0
  FILE *fp = (FILE *)p;
1240
1241
#ifdef notyet
1242
  if (ferror(fp))
1243
    return-an-error;
1244
  /* XXX should check return from fflush()/fclose() too */
1245
#endif
1246
  /* Don't close the standard output, but *do* flush it */
1247
0
  if (fp == stdout)
1248
0
    (void)fflush(fp);
1249
0
  else
1250
0
    (void)fclose(fp);
1251
0
}