Coverage Report

Created: 2025-12-14 06:20

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
58.4k
#define TCPDUMP_MAGIC   0xa1b2c3d4
72
73
/*
74
 * Alexey Kuznetzov's modified libpcap format.
75
 */
76
73.0k
#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
42.3k
#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
18.8k
{
221
18.8k
  bpf_u_int32 magic_int;
222
18.8k
  struct pcap_file_header hdr;
223
18.8k
  size_t amt_read;
224
18.8k
  pcap_t *p;
225
18.8k
  int swapped = 0;
226
18.8k
  struct pcap_sf *ps;
227
228
  /*
229
   * Assume no read errors.
230
   */
231
18.8k
  *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
18.8k
  memcpy(&magic_int, magic, sizeof(magic_int));
239
18.8k
  if (magic_int != TCPDUMP_MAGIC &&
240
18.5k
      magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
241
17.1k
      magic_int != NSEC_TCPDUMP_MAGIC) {
242
10.3k
    magic_int = SWAPLONG(magic_int);
243
10.3k
    if (magic_int != TCPDUMP_MAGIC &&
244
9.25k
        magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
245
9.18k
        magic_int != NSEC_TCPDUMP_MAGIC)
246
2.71k
      return (NULL);  /* nope */
247
7.68k
    swapped = 1;
248
7.68k
  }
249
250
  /*
251
   * They are.  Put the magic number in the header, and read
252
   * the rest of the header.
253
   */
254
16.1k
  hdr.magic = magic_int;
255
16.1k
  amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
256
16.1k
      sizeof(hdr) - sizeof(hdr.magic), fp);
257
16.1k
  if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
258
28
    if (ferror(fp)) {
259
0
      pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
260
0
          errno, "error reading dump file");
261
28
    } else {
262
28
      snprintf(errbuf, PCAP_ERRBUF_SIZE,
263
28
          "truncated dump file; tried to read %zu file header bytes, only got %zu",
264
28
          sizeof(hdr), amt_read);
265
28
    }
266
28
    *err = 1;
267
28
    return (NULL);
268
28
  }
269
270
  /*
271
   * If it's a byte-swapped capture file, byte-swap the header.
272
   */
273
16.0k
  if (swapped) {
274
7.66k
    hdr.version_major = SWAPSHORT(hdr.version_major);
275
7.66k
    hdr.version_minor = SWAPSHORT(hdr.version_minor);
276
7.66k
    hdr.thiszone = SWAPLONG(hdr.thiszone);
277
7.66k
    hdr.sigfigs = SWAPLONG(hdr.sigfigs);
278
7.66k
    hdr.snaplen = SWAPLONG(hdr.snaplen);
279
7.66k
    hdr.linktype = SWAPLONG(hdr.linktype);
280
7.66k
  }
281
282
  /*
283
   * currently only versions 2.[0-4] are supported with
284
   * the exception of 543.0 for DG/UX tcpdump.
285
   */
286
16.0k
  if (! ((hdr.version_major == PCAP_VERSION_MAJOR &&
287
15.9k
    hdr.version_minor <= PCAP_VERSION_MINOR) ||
288
224
         (hdr.version_major == 543 &&
289
144
    hdr.version_minor == 0))) {
290
110
    snprintf(errbuf, PCAP_ERRBUF_SIZE,
291
110
       "unsupported pcap savefile version %u.%u",
292
110
       hdr.version_major, hdr.version_minor);
293
110
    *err = 1;
294
110
    return NULL;
295
110
  }
296
297
  /*
298
   * Check the main reserved field.
299
   */
300
15.9k
  if (LT_RESERVED1(hdr.linktype) != 0) {
301
21
    snprintf(errbuf, PCAP_ERRBUF_SIZE,
302
21
       "savefile linktype reserved field not zero (0x%08x)",
303
21
       LT_RESERVED1(hdr.linktype));
304
21
    *err = 1;
305
21
    return NULL;
306
21
  }
307
308
  /*
309
   * OK, this is a good pcap file.
310
   * Allocate a pcap_t for it.
311
   */
312
15.9k
  p = PCAP_OPEN_OFFLINE_COMMON(errbuf, struct pcap_sf);
313
15.9k
  if (p == NULL) {
314
    /* Allocation failed. */
315
0
    *err = 1;
316
0
    return (NULL);
317
0
  }
318
15.9k
  p->swapped = swapped;
319
15.9k
  p->version_major = hdr.version_major;
320
15.9k
  p->version_minor = hdr.version_minor;
321
15.9k
  p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
322
15.9k
  p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
323
15.9k
  p->snapshot = pcapint_adjust_snapshot(p->linktype, hdr.snaplen);
324
325
15.9k
  p->next_packet_op = pcap_next_packet;
326
327
15.9k
  ps = p->priv;
328
329
15.9k
  p->opt.tstamp_precision = precision;
330
331
  /*
332
   * Will we need to scale the timestamps to match what the
333
   * user wants?
334
   */
335
15.9k
  switch (precision) {
336
337
15.9k
  case PCAP_TSTAMP_PRECISION_MICRO:
338
15.9k
    if (magic_int == NSEC_TCPDUMP_MAGIC) {
339
      /*
340
       * The file has nanoseconds, the user
341
       * wants microseconds; scale the
342
       * precision down.
343
       */
344
13.1k
      ps->scale_type = SCALE_DOWN;
345
13.1k
    } else {
346
      /*
347
       * The file has microseconds, the
348
       * user wants microseconds; nothing to do.
349
       */
350
2.79k
      ps->scale_type = PASS_THROUGH;
351
2.79k
    }
352
15.9k
    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
15.9k
  }
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
15.9k
  switch (hdr.version_major) {
390
391
15.8k
  case 2:
392
15.8k
    if (hdr.version_minor < 3)
393
11.1k
      ps->lengths_swapped = SWAPPED;
394
4.71k
    else if (hdr.version_minor == 3)
395
3.51k
      ps->lengths_swapped = MAYBE_SWAPPED;
396
1.19k
    else
397
1.19k
      ps->lengths_swapped = NOT_SWAPPED;
398
15.8k
    break;
399
400
113
  case 543:
401
113
    ps->lengths_swapped = SWAPPED;
402
113
    break;
403
404
0
  default:
405
0
    ps->lengths_swapped = NOT_SWAPPED;
406
0
    break;
407
15.9k
  }
408
409
15.9k
  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
1.41k
    ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
428
429
1.41k
    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
179
      if (p->snapshot <= INT_MAX - 14)
454
174
        p->snapshot += 14;
455
5
      else
456
5
        p->snapshot = INT_MAX;
457
179
    }
458
1.41k
  } else
459
14.5k
    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
15.9k
  p->bufsize = p->snapshot;
471
15.9k
  if (p->bufsize > 2048)
472
14.4k
    p->bufsize = 2048;
473
15.9k
  p->buffer = malloc(p->bufsize);
474
15.9k
  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
15.9k
  p->cleanup_op = pcapint_sf_cleanup;
482
483
15.9k
  return (p);
484
15.9k
}
485
486
/*
487
 * Grow the packet buffer to the specified size.
488
 */
489
static int
490
grow_buffer(pcap_t *p, u_int bufsize)
491
7.93k
{
492
7.93k
  void *bigger_buffer;
493
494
7.93k
  bigger_buffer = realloc(p->buffer, bufsize);
495
7.93k
  if (bigger_buffer == NULL) {
496
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
497
0
    return (0);
498
0
  }
499
7.93k
  p->buffer = bigger_buffer;
500
7.93k
  p->bufsize = bufsize;
501
7.93k
  return (1);
502
7.93k
}
503
504
/*
505
 * Read and return the next packet from the savefile.  Return the header
506
 * in hdr and a pointer to the contents in data.  Return 1 on success, 0
507
 * if there were no more packets, and -1 on an error.
508
 */
509
static int
510
pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
511
62.5k
{
512
62.5k
  struct pcap_sf *ps = p->priv;
513
62.5k
  struct pcap_sf_patched_pkthdr sf_hdr;
514
62.5k
  FILE *fp = p->rfile;
515
62.5k
  size_t amt_read;
516
62.5k
  bpf_u_int32 t;
517
518
  /*
519
   * Read the packet header; the structure we use as a buffer
520
   * is the longer structure for files generated by the patched
521
   * libpcap, but if the file has the magic number for an
522
   * unpatched libpcap we only read as many bytes as the regular
523
   * header has.
524
   */
525
62.5k
  amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
526
62.5k
  if (amt_read != ps->hdrsize) {
527
9.43k
    if (ferror(fp)) {
528
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
529
0
          errno, "error reading dump file");
530
0
      return (-1);
531
9.43k
    } else {
532
9.43k
      if (amt_read != 0) {
533
332
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
534
332
            "truncated dump file; tried to read %zu header bytes, only got %zu",
535
332
            ps->hdrsize, amt_read);
536
332
        return (-1);
537
332
      }
538
      /* EOF */
539
9.10k
      return (0);
540
9.43k
    }
541
9.43k
  }
542
543
53.0k
  if (p->swapped) {
544
    /* these were written in opposite byte order */
545
49.5k
    hdr->caplen = SWAPLONG(sf_hdr.caplen);
546
49.5k
    hdr->len = SWAPLONG(sf_hdr.len);
547
49.5k
    hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec);
548
49.5k
    hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec);
549
49.5k
  } else {
550
3.53k
    hdr->caplen = sf_hdr.caplen;
551
3.53k
    hdr->len = sf_hdr.len;
552
3.53k
    hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
553
3.53k
    hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
554
3.53k
  }
555
556
53.0k
  switch (ps->scale_type) {
557
558
10.4k
  case PASS_THROUGH:
559
    /*
560
     * Just pass the time stamp through.
561
     */
562
10.4k
    break;
563
564
0
  case SCALE_UP:
565
    /*
566
     * File has microseconds, user wants nanoseconds; convert
567
     * it.
568
     */
569
0
    hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
570
0
    break;
571
572
42.5k
  case SCALE_DOWN:
573
    /*
574
     * File has nanoseconds, user wants microseconds; convert
575
     * it.
576
     */
577
42.5k
    hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
578
42.5k
    break;
579
53.0k
  }
580
581
  /* Swap the caplen and len fields, if necessary. */
582
53.0k
  switch (ps->lengths_swapped) {
583
584
5.91k
  case NOT_SWAPPED:
585
5.91k
    break;
586
587
26.6k
  case MAYBE_SWAPPED:
588
26.6k
    if (hdr->caplen <= hdr->len) {
589
      /*
590
       * The captured length is <= the actual length,
591
       * so presumably they weren't swapped.
592
       */
593
18.2k
      break;
594
18.2k
    }
595
    /* FALLTHROUGH */
596
597
28.9k
  case SWAPPED:
598
28.9k
    t = hdr->caplen;
599
28.9k
    hdr->caplen = hdr->len;
600
28.9k
    hdr->len = t;
601
28.9k
    break;
602
53.0k
  }
603
604
  /*
605
   * Is the packet bigger than we consider sane?
606
   */
607
53.0k
  if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) {
608
    /*
609
     * Yes.  This may be a damaged or fuzzed file.
610
     *
611
     * Is it bigger than the snapshot length?
612
     * (We don't treat that as an error if it's not
613
     * bigger than the maximum we consider sane; see
614
     * below.)
615
     */
616
172
    if (hdr->caplen > (bpf_u_int32)p->snapshot) {
617
144
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
618
144
          "invalid packet capture length %u, bigger than "
619
144
          "snaplen of %d", hdr->caplen, p->snapshot);
620
144
    } else {
621
28
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
622
28
          "invalid packet capture length %u, bigger than "
623
28
          "maximum of %u", hdr->caplen,
624
28
          max_snaplen_for_dlt(p->linktype));
625
28
    }
626
172
    return (-1);
627
172
  }
628
629
52.9k
  if (hdr->caplen > (bpf_u_int32)p->snapshot) {
630
    /*
631
     * The packet is bigger than the snapshot length
632
     * for this file.
633
     *
634
     * This can happen due to Solaris 2.3 systems tripping
635
     * over the BUFMOD problem and not setting the snapshot
636
     * length correctly in the savefile header.
637
     *
638
     * libpcap 0.4 and later on Solaris 2.3 should set the
639
     * snapshot length correctly in the pcap file header,
640
     * even though they don't set a snapshot length in bufmod
641
     * (the buggy bufmod chops off the *beginning* of the
642
     * packet if a snapshot length is specified); they should
643
     * also reduce the captured length, as supplied to the
644
     * per-packet callback, to the snapshot length if it's
645
     * greater than the snapshot length, so the code using
646
     * libpcap should see the packet cut off at the snapshot
647
     * length, even though the full packet is copied up to
648
     * userland.
649
     *
650
     * However, perhaps some versions of libpcap failed to
651
     * set the snapshot length correctly in the file header
652
     * or the per-packet header, or perhaps this is a
653
     * corrupted savefile or a savefile built/modified by a
654
     * fuzz tester, so we check anyway.  We grow the buffer
655
     * to be big enough for the snapshot length, read up
656
     * to the snapshot length, discard the rest of the
657
     * packet, and report the snapshot length as the captured
658
     * length; we don't want to hand our caller a packet
659
     * bigger than the snapshot length, because they might
660
     * be assuming they'll never be handed such a packet,
661
     * and might copy the packet into a snapshot-length-
662
     * sized buffer, assuming it'll fit.
663
     */
664
7.56k
    size_t bytes_to_discard;
665
7.56k
    size_t bytes_to_read, bytes_read;
666
7.56k
    char discard_buf[4096];
667
668
7.56k
    if (hdr->caplen > p->bufsize) {
669
      /*
670
       * Grow the buffer to the snapshot length.
671
       */
672
7.56k
      if (!grow_buffer(p, p->snapshot))
673
0
        return (-1);
674
7.56k
    }
675
676
    /*
677
     * Read the first p->snapshot bytes into the buffer.
678
     */
679
7.56k
    amt_read = fread(p->buffer, 1, p->snapshot, fp);
680
7.56k
    if (amt_read != (bpf_u_int32)p->snapshot) {
681
108
      if (ferror(fp)) {
682
0
        pcapint_fmt_errmsg_for_errno(p->errbuf,
683
0
             PCAP_ERRBUF_SIZE, errno,
684
0
            "error reading dump file");
685
108
      } else {
686
        /*
687
         * Yes, this uses hdr->caplen; technically,
688
         * it's true, because we would try to read
689
         * and discard the rest of those bytes, and
690
         * that would fail because we got EOF before
691
         * the read finished.
692
         */
693
108
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
694
108
            "truncated dump file; tried to read %d captured bytes, only got %zu",
695
108
            p->snapshot, amt_read);
696
108
      }
697
108
      return (-1);
698
108
    }
699
700
    /*
701
     * Now read and discard what's left.
702
     */
703
7.45k
    bytes_to_discard = hdr->caplen - p->snapshot;
704
7.45k
    bytes_read = amt_read;
705
14.8k
    while (bytes_to_discard != 0) {
706
7.53k
      bytes_to_read = bytes_to_discard;
707
7.53k
      if (bytes_to_read > sizeof (discard_buf))
708
148
        bytes_to_read = sizeof (discard_buf);
709
7.53k
      amt_read = fread(discard_buf, 1, bytes_to_read, fp);
710
7.53k
      bytes_read += amt_read;
711
7.53k
      if (amt_read != bytes_to_read) {
712
105
        if (ferror(fp)) {
713
0
          pcapint_fmt_errmsg_for_errno(p->errbuf,
714
0
              PCAP_ERRBUF_SIZE, errno,
715
0
              "error reading dump file");
716
105
        } else {
717
105
          snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
718
105
              "truncated dump file; tried to read %u captured bytes, only got %zu",
719
105
              hdr->caplen, bytes_read);
720
105
        }
721
105
        return (-1);
722
105
      }
723
7.43k
      bytes_to_discard -= amt_read;
724
7.43k
    }
725
726
    /*
727
     * Adjust caplen accordingly, so we don't get confused later
728
     * as to how many bytes we have to play with.
729
     */
730
7.34k
    hdr->caplen = p->snapshot;
731
45.3k
  } else {
732
    /*
733
     * The packet is within the snapshot length for this file.
734
     */
735
45.3k
    if (hdr->caplen > p->bufsize) {
736
      /*
737
       * Grow the buffer to the next power of 2, or
738
       * the snaplen, whichever is lower.
739
       */
740
373
      u_int new_bufsize;
741
742
373
      new_bufsize = hdr->caplen;
743
      /*
744
       * https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
745
       */
746
373
      new_bufsize--;
747
373
      new_bufsize |= new_bufsize >> 1;
748
373
      new_bufsize |= new_bufsize >> 2;
749
373
      new_bufsize |= new_bufsize >> 4;
750
373
      new_bufsize |= new_bufsize >> 8;
751
373
      new_bufsize |= new_bufsize >> 16;
752
373
      new_bufsize++;
753
754
373
      if (new_bufsize > (u_int)p->snapshot)
755
66
        new_bufsize = p->snapshot;
756
757
373
      if (!grow_buffer(p, new_bufsize))
758
0
        return (-1);
759
373
    }
760
761
    /* read the packet itself */
762
45.3k
    amt_read = fread(p->buffer, 1, hdr->caplen, fp);
763
45.3k
    if (amt_read != hdr->caplen) {
764
184
      if (ferror(fp)) {
765
0
        pcapint_fmt_errmsg_for_errno(p->errbuf,
766
0
            PCAP_ERRBUF_SIZE, errno,
767
0
            "error reading dump file");
768
184
      } else {
769
184
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
770
184
            "truncated dump file; tried to read %u captured bytes, only got %zu",
771
184
            hdr->caplen, amt_read);
772
184
      }
773
184
      return (-1);
774
184
    }
775
45.3k
  }
776
52.5k
  *data = p->buffer;
777
778
52.5k
  pcapint_post_process(p->linktype, p->swapped, hdr, *data);
779
780
52.5k
  return (1);
781
52.9k
}
782
783
static int
784
sf_write_header(pcap_t *p, FILE *fp, int linktype, int snaplen)
785
0
{
786
0
  struct pcap_file_header hdr;
787
788
0
  hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
789
0
  hdr.version_major = PCAP_VERSION_MAJOR;
790
0
  hdr.version_minor = PCAP_VERSION_MINOR;
791
792
  /*
793
   * https://www.tcpdump.org/manpages/pcap-savefile.5.txt states:
794
   * thiszone (Reserved1): 4-byte not used - SHOULD be filled with 0
795
   * sigfigs (Reserved2):  4-byte not used - SHOULD be filled with 0
796
   */
797
0
  hdr.thiszone = 0;
798
0
  hdr.sigfigs = 0;
799
0
  hdr.snaplen = snaplen;
800
0
  hdr.linktype = linktype;
801
802
0
  if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
803
0
    return (-1);
804
805
0
  return (0);
806
0
}
807
808
/*
809
 * Output a packet to the initialized dump file.
810
 */
811
void
812
pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
813
0
{
814
0
  FILE *f;
815
0
  struct pcap_sf_pkthdr sf_hdr;
816
817
0
  f = (FILE *)user;
818
  /*
819
   * If the output file handle is in an error state, don't write
820
   * anything.
821
   *
822
   * While in principle a file handle can return from an error state
823
   * to a normal state (for example if a disk that is full has space
824
   * freed), we have possibly left a broken file already, and won't
825
   * be able to clean it up. The safest option is to do nothing.
826
   *
827
   * Note that if we could guarantee that fwrite() was atomic we
828
   * might be able to insure that we don't produce a corrupted file,
829
   * but the standard defines fwrite() as a series of fputc() calls,
830
   * so we really have no insurance that things are not fubared.
831
   *
832
   * http://pubs.opengroup.org/onlinepubs/009695399/functions/fwrite.html
833
   */
834
0
  if (ferror(f))
835
0
    return;
836
  /*
837
   * Better not try writing pcap files after
838
   * 2106-02-07 06:28:15 UTC; switch to pcapng.
839
   * (And better not try writing pcap files with time stamps
840
   * that predate 1970-01-01 00:00:00 UTC; that's not supported.
841
   * You could try using pcapng with the if_tsoffset field in
842
   * the IDB for the interface(s) with packets with those time
843
   * stamps, but you may also have to get a link-layer type for
844
   * IBM Bisync or whatever link layer even older forms
845
   * of computer communication used.)
846
   */
847
0
  sf_hdr.ts.tv_sec  = (bpf_u_int32)h->ts.tv_sec;
848
0
  sf_hdr.ts.tv_usec = (bpf_u_int32)h->ts.tv_usec;
849
0
  sf_hdr.caplen     = h->caplen;
850
0
  sf_hdr.len        = h->len;
851
  /*
852
   * We only write the packet if we can write the header properly.
853
   *
854
   * This doesn't prevent us from having corrupted output, and if we
855
   * for some reason don't get a complete write we don't have any
856
   * way to set ferror() to prevent future writes from being
857
   * attempted, but it is better than nothing.
858
   */
859
0
  if (fwrite(&sf_hdr, sizeof(sf_hdr), 1, f) == 1) {
860
0
    (void)fwrite(sp, h->caplen, 1, f);
861
0
  }
862
0
}
863
864
static pcap_dumper_t *
865
pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
866
0
{
867
868
#if defined(_WIN32)
869
  /*
870
   * If we're writing to the standard output, put it in binary
871
   * mode, as savefiles are binary files.
872
   *
873
   * Otherwise, we turn off buffering.
874
   * XXX - why?  And why not on the standard output?
875
   */
876
  if (f == stdout)
877
    SET_BINMODE(f);
878
  else
879
    setvbuf(f, NULL, _IONBF, 0);
880
#endif
881
0
  if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
882
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
883
0
        errno, "Can't write to %s", fname);
884
0
    if (f != stdout)
885
0
      (void)fclose(f);
886
0
    return (NULL);
887
0
  }
888
0
  return ((pcap_dumper_t *)f);
889
0
}
890
891
/*
892
 * Initialize so that sf_write() will output to the file named 'fname'.
893
 */
894
pcap_dumper_t *
895
pcap_dump_open(pcap_t *p, const char *fname)
896
0
{
897
0
  FILE *f;
898
0
  int linktype;
899
900
  /*
901
   * If this pcap_t hasn't been activated, it doesn't have a
902
   * link-layer type, so we can't use it.
903
   */
904
0
  if (!p->activated) {
905
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
906
0
        "%s: not-yet-activated pcap_t passed to pcap_dump_open",
907
0
        fname);
908
0
    return (NULL);
909
0
  }
910
0
  linktype = dlt_to_linktype(p->linktype);
911
0
  if (linktype == -1) {
912
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
913
0
        "%s: link-layer type %d isn't supported in savefiles",
914
0
        fname, p->linktype);
915
0
    return (NULL);
916
0
  }
917
0
  linktype |= p->linktype_ext;
918
919
0
  if (fname == NULL) {
920
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
921
0
        "A null pointer was supplied as the file name");
922
0
    return NULL;
923
0
  }
924
0
  if (fname[0] == '-' && fname[1] == '\0') {
925
0
    f = stdout;
926
0
    fname = "standard output";
927
0
  } else {
928
    /*
929
     * "b" is supported as of C90, so *all* UN*Xes should
930
     * support it, even though it does nothing.  It's
931
     * required on Windows, as the file is a binary file
932
     * and must be written in binary mode.
933
     */
934
0
    f = pcapint_charset_fopen(fname, "wb");
935
0
    if (f == NULL) {
936
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
937
0
          errno, "%s", fname);
938
0
      return (NULL);
939
0
    }
940
0
  }
941
0
  return (pcap_setup_dump(p, linktype, f, fname));
942
0
}
943
944
#ifdef _WIN32
945
/*
946
 * Initialize so that sf_write() will output to a stream wrapping the given raw
947
 * OS file HANDLE.
948
 */
949
pcap_dumper_t *
950
pcap_dump_hopen(pcap_t *p, intptr_t osfd)
951
{
952
  int fd;
953
  FILE *file;
954
955
  fd = _open_osfhandle(osfd, _O_APPEND);
956
  if (fd < 0) {
957
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
958
        errno, "_open_osfhandle");
959
    return NULL;
960
  }
961
962
  file = _fdopen(fd, "wb");
963
  if (file == NULL) {
964
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
965
        errno, "_fdopen");
966
    _close(fd);
967
    return NULL;
968
  }
969
970
  return pcap_dump_fopen(p, file);
971
}
972
#endif /* _WIN32 */
973
974
/*
975
 * Initialize so that sf_write() will output to the given stream.
976
 */
977
#ifdef _WIN32
978
static
979
#endif /* _WIN32 */
980
pcap_dumper_t *
981
pcap_dump_fopen(pcap_t *p, FILE *f)
982
0
{
983
0
  int linktype;
984
985
0
  linktype = dlt_to_linktype(p->linktype);
986
0
  if (linktype == -1) {
987
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
988
0
        "stream: link-layer type %d isn't supported in savefiles",
989
0
        p->linktype);
990
0
    return (NULL);
991
0
  }
992
0
  linktype |= p->linktype_ext;
993
994
0
  return (pcap_setup_dump(p, linktype, f, "stream"));
995
0
}
996
997
pcap_dumper_t *
998
pcap_dump_open_append(pcap_t *p, const char *fname)
999
0
{
1000
0
  FILE *f;
1001
0
  int linktype;
1002
0
  size_t amt_read;
1003
0
  struct pcap_file_header ph;
1004
1005
0
  linktype = dlt_to_linktype(p->linktype);
1006
0
  if (linktype == -1) {
1007
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1008
0
        "%s: link-layer type %d isn't supported in savefiles",
1009
0
        fname, linktype);
1010
0
    return (NULL);
1011
0
  }
1012
1013
0
  if (fname == NULL) {
1014
0
    snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1015
0
        "A null pointer was supplied as the file name");
1016
0
    return NULL;
1017
0
  }
1018
0
  if (fname[0] == '-' && fname[1] == '\0')
1019
0
    return (pcap_setup_dump(p, linktype, stdout, "standard output"));
1020
1021
  /*
1022
   * "a" will cause the file *not* to be truncated if it exists
1023
   * but will cause it to be created if it doesn't.  It will
1024
   * also cause all writes to be done at the end of the file,
1025
   * but will allow reads to be done anywhere in the file.  This
1026
   * is what we need, because we need to read from the beginning
1027
   * of the file to see if it already has a header and packets
1028
   * or if it doesn't.
1029
   *
1030
   * "b" is supported as of C90, so *all* UN*Xes should support it,
1031
   * even though it does nothing.  It's required on Windows, as the
1032
   * file is a binary file and must be read in binary mode.
1033
   */
1034
0
  f = pcapint_charset_fopen(fname, "ab+");
1035
0
  if (f == NULL) {
1036
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1037
0
        errno, "%s", fname);
1038
0
    return (NULL);
1039
0
  }
1040
1041
  /*
1042
   * Try to read a pcap header.
1043
   *
1044
   * We do not assume that the file will be positioned at the
1045
   * beginning immediately after we've opened it - we seek to
1046
   * the beginning.  ISO C says it's implementation-defined
1047
   * whether the file position indicator is at the beginning
1048
   * or the end of the file after an append-mode open, and
1049
   * it wasn't obvious from the Single UNIX Specification
1050
   * or the Microsoft documentation how that works on SUS-
1051
   * compliant systems or on Windows.
1052
   */
1053
0
  if (fseek(f, 0, SEEK_SET) == -1) {
1054
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1055
0
        errno, "Can't seek to the beginning of %s", fname);
1056
0
    (void)fclose(f);
1057
0
    return (NULL);
1058
0
  }
1059
0
  amt_read = fread(&ph, 1, sizeof (ph), f);
1060
0
  if (amt_read != sizeof (ph)) {
1061
0
    if (ferror(f)) {
1062
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1063
0
          errno, "%s", fname);
1064
0
      (void)fclose(f);
1065
0
      return (NULL);
1066
0
    } else if (feof(f) && amt_read > 0) {
1067
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1068
0
          "%s: truncated pcap file header", fname);
1069
0
      (void)fclose(f);
1070
0
      return (NULL);
1071
0
    }
1072
0
  }
1073
1074
#if defined(_WIN32)
1075
  /*
1076
   * We turn off buffering.
1077
   * XXX - why?  And why not on the standard output?
1078
   */
1079
  setvbuf(f, NULL, _IONBF, 0);
1080
#endif
1081
1082
  /*
1083
   * If a header is already present and:
1084
   *
1085
   *  it's not for a pcap file of the appropriate resolution
1086
   *  and the right byte order for this machine;
1087
   *
1088
   *  the link-layer header types don't match;
1089
   *
1090
   *  the snapshot lengths don't match;
1091
   *
1092
   * return an error.
1093
   */
1094
0
  if (amt_read > 0) {
1095
    /*
1096
     * A header is already present.
1097
     * Do the checks.
1098
     */
1099
0
    switch (ph.magic) {
1100
1101
0
    case TCPDUMP_MAGIC:
1102
0
      if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
1103
0
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1104
0
            "%s: different time stamp precision, cannot append to file", fname);
1105
0
        (void)fclose(f);
1106
0
        return (NULL);
1107
0
      }
1108
0
      break;
1109
1110
0
    case NSEC_TCPDUMP_MAGIC:
1111
0
      if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
1112
0
        snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1113
0
            "%s: different time stamp precision, cannot append to file", fname);
1114
0
        (void)fclose(f);
1115
0
        return (NULL);
1116
0
      }
1117
0
      break;
1118
1119
0
    case SWAPLONG(TCPDUMP_MAGIC):
1120
0
    case SWAPLONG(NSEC_TCPDUMP_MAGIC):
1121
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1122
0
          "%s: different byte order, cannot append to file", fname);
1123
0
      (void)fclose(f);
1124
0
      return (NULL);
1125
1126
0
    case KUZNETZOV_TCPDUMP_MAGIC:
1127
0
    case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC):
1128
0
    case NAVTEL_TCPDUMP_MAGIC:
1129
0
    case SWAPLONG(NAVTEL_TCPDUMP_MAGIC):
1130
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1131
0
          "%s: not a pcap file to which we can append", fname);
1132
0
      (void)fclose(f);
1133
0
      return (NULL);
1134
1135
0
    default:
1136
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1137
0
          "%s: not a pcap file", fname);
1138
0
      (void)fclose(f);
1139
0
      return (NULL);
1140
0
    }
1141
1142
    /*
1143
     * Good version?
1144
     */
1145
0
    if (ph.version_major != PCAP_VERSION_MAJOR ||
1146
0
        ph.version_minor != PCAP_VERSION_MINOR) {
1147
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1148
0
          "%s: version is %u.%u, cannot append to file", fname,
1149
0
          ph.version_major, ph.version_minor);
1150
0
      (void)fclose(f);
1151
0
      return (NULL);
1152
0
    }
1153
0
    if ((bpf_u_int32)linktype != ph.linktype) {
1154
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1155
0
          "%s: different linktype, cannot append to file", fname);
1156
0
      (void)fclose(f);
1157
0
      return (NULL);
1158
0
    }
1159
0
    if ((bpf_u_int32)p->snapshot != ph.snaplen) {
1160
0
      snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1161
0
          "%s: different snaplen, cannot append to file", fname);
1162
0
      (void)fclose(f);
1163
0
      return (NULL);
1164
0
    }
1165
0
  } else {
1166
    /*
1167
     * A header isn't present; attempt to write it.
1168
     */
1169
0
    if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
1170
0
      pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1171
0
          errno, "Can't write to %s", fname);
1172
0
      (void)fclose(f);
1173
0
      return (NULL);
1174
0
    }
1175
0
  }
1176
1177
  /*
1178
   * Start writing at the end of the file.
1179
   *
1180
   * XXX - this shouldn't be necessary, given that we're opening
1181
   * the file in append mode, and ISO C specifies that all writes
1182
   * are done at the end of the file in that mode.
1183
   */
1184
0
  if (fseek(f, 0, SEEK_END) == -1) {
1185
0
    pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1186
0
        errno, "Can't seek to the end of %s", fname);
1187
0
    (void)fclose(f);
1188
0
    return (NULL);
1189
0
  }
1190
0
  return ((pcap_dumper_t *)f);
1191
0
}
1192
1193
FILE *
1194
pcap_dump_file(pcap_dumper_t *p)
1195
0
{
1196
0
  return ((FILE *)p);
1197
0
}
1198
1199
long
1200
pcap_dump_ftell(pcap_dumper_t *p)
1201
0
{
1202
0
  return (ftell((FILE *)p));
1203
0
}
1204
1205
#if defined(HAVE_FSEEKO)
1206
/*
1207
 * We have fseeko(), so we have ftello().
1208
 * If we have large file support (files larger than 2^31-1 bytes),
1209
 * ftello() will give us a current file position with more than 32
1210
 * bits.
1211
 */
1212
int64_t
1213
pcap_dump_ftell64(pcap_dumper_t *p)
1214
0
{
1215
0
  return (ftello((FILE *)p));
1216
0
}
1217
#elif defined(_MSC_VER)
1218
/*
1219
 * We have Visual Studio; we support only 2015 and later, so we have
1220
 * _ftelli64().
1221
 */
1222
int64_t
1223
pcap_dump_ftell64(pcap_dumper_t *p)
1224
{
1225
  return (_ftelli64((FILE *)p));
1226
}
1227
#else
1228
/*
1229
 * We don't have ftello() or _ftelli64(), so fall back on ftell().
1230
 * Either long is 64 bits, in which case ftell() should suffice,
1231
 * or this is probably an older 32-bit UN*X without large file
1232
 * support, which means you'll probably get errors trying to
1233
 * write files > 2^31-1, so it won't matter anyway.
1234
 *
1235
 * XXX - what about MinGW?
1236
 */
1237
int64_t
1238
pcap_dump_ftell64(pcap_dumper_t *p)
1239
{
1240
  return (ftell((FILE *)p));
1241
}
1242
#endif
1243
1244
int
1245
pcap_dump_flush(pcap_dumper_t *p)
1246
0
{
1247
1248
0
  if (fflush((FILE *)p) == EOF)
1249
0
    return (-1);
1250
0
  else
1251
0
    return (0);
1252
0
}
1253
1254
void
1255
pcap_dump_close(pcap_dumper_t *p)
1256
0
{
1257
0
  FILE *fp = (FILE *)p;
1258
1259
#ifdef notyet
1260
  if (ferror(fp))
1261
    return-an-error;
1262
  /* XXX should check return from fflush()/fclose() too */
1263
#endif
1264
  /* Don't close the standard output, but *do* flush it */
1265
0
  if (fp == stdout)
1266
0
    (void)fflush(fp);
1267
0
  else
1268
0
    (void)fclose(fp);
1269
0
}