]> The Tcpdump Group git mirrors - libpcap/blob - sf-pcap.c
update configure and cmake
[libpcap] / sf-pcap.c
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 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include <pcap-types.h>
36 #ifdef _WIN32
37 #include <io.h>
38 #include <fcntl.h>
39 #endif /* _WIN32 */
40
41 #include <errno.h>
42 #include <memory.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <limits.h> /* for INT_MAX */
47
48 #include "pcap-int.h"
49
50 #include "pcap-common.h"
51
52 #ifdef HAVE_OS_PROTO_H
53 #include "os-proto.h"
54 #endif
55
56 #include "sf-pcap.h"
57
58 /*
59 * Setting O_BINARY on DOS/Windows is a bit tricky
60 */
61 #if defined(_WIN32)
62 #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
63 #elif defined(MSDOS)
64 #if defined(__HIGHC__)
65 #define SET_BINMODE(f) setmode(f, O_BINARY)
66 #else
67 #define SET_BINMODE(f) setmode(fileno(f), O_BINARY)
68 #endif
69 #endif
70
71 /*
72 * Standard libpcap format.
73 */
74 #define TCPDUMP_MAGIC 0xa1b2c3d4
75
76 /*
77 * Alexey Kuznetzov's modified libpcap format.
78 */
79 #define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
80
81 /*
82 * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt>
83 * for another modified format.
84 */
85 #define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd
86
87 /*
88 * Navtel Communcations' format, with nanosecond timestamps,
89 * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
90 */
91 #define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d
92
93 /*
94 * Normal libpcap format, except for seconds/nanoseconds timestamps,
95 * as per a request by Ulf Lamping <ulf.lamping@web.de>
96 */
97 #define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
98
99 /*
100 * Mechanism for storing information about a capture in the upper
101 * 6 bits of a linktype value in a capture file.
102 *
103 * LT_LINKTYPE_EXT(x) extracts the additional information.
104 *
105 * The rest of the bits are for a value describing the link-layer
106 * value. LT_LINKTYPE(x) extracts that value.
107 */
108 #define LT_LINKTYPE(x) ((x) & 0x03FFFFFF)
109 #define LT_LINKTYPE_EXT(x) ((x) & 0xFC000000)
110
111 static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
112
113 /*
114 * Private data for reading pcap savefiles.
115 */
116 typedef enum {
117 NOT_SWAPPED,
118 SWAPPED,
119 MAYBE_SWAPPED
120 } swapped_type_t;
121
122 typedef enum {
123 PASS_THROUGH,
124 SCALE_UP,
125 SCALE_DOWN
126 } tstamp_scale_type_t;
127
128 struct pcap_sf {
129 size_t hdrsize;
130 swapped_type_t lengths_swapped;
131 tstamp_scale_type_t scale_type;
132 };
133
134 /*
135 * Check whether this is a pcap savefile and, if it is, extract the
136 * relevant information from the header.
137 */
138 pcap_t *
139 pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf,
140 int *err)
141 {
142 struct pcap_file_header hdr;
143 size_t amt_read;
144 pcap_t *p;
145 int swapped = 0;
146 struct pcap_sf *ps;
147
148 /*
149 * Assume no read errors.
150 */
151 *err = 0;
152
153 /*
154 * Check whether the first 4 bytes of the file are the magic
155 * number for a pcap savefile, or for a byte-swapped pcap
156 * savefile.
157 */
158 if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
159 magic != NSEC_TCPDUMP_MAGIC) {
160 magic = SWAPLONG(magic);
161 if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC &&
162 magic != NSEC_TCPDUMP_MAGIC)
163 return (NULL); /* nope */
164 swapped = 1;
165 }
166
167 /*
168 * They are. Put the magic number in the header, and read
169 * the rest of the header.
170 */
171 hdr.magic = magic;
172 amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
173 sizeof(hdr) - sizeof(hdr.magic), fp);
174 if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
175 if (ferror(fp)) {
176 pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
177 errno, "error reading dump file");
178 } else {
179 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
180 "truncated dump file; tried to read %" PRIsize " file header bytes, only got %" PRIsize,
181 sizeof(hdr), amt_read);
182 }
183 *err = 1;
184 return (NULL);
185 }
186
187 /*
188 * If it's a byte-swapped capture file, byte-swap the header.
189 */
190 if (swapped) {
191 hdr.version_major = SWAPSHORT(hdr.version_major);
192 hdr.version_minor = SWAPSHORT(hdr.version_minor);
193 hdr.thiszone = SWAPLONG(hdr.thiszone);
194 hdr.sigfigs = SWAPLONG(hdr.sigfigs);
195 hdr.snaplen = SWAPLONG(hdr.snaplen);
196 hdr.linktype = SWAPLONG(hdr.linktype);
197 }
198
199 if (hdr.version_major < PCAP_VERSION_MAJOR) {
200 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
201 "archaic pcap savefile format");
202 *err = 1;
203 return (NULL);
204 }
205
206 /*
207 * currently only versions 2.[0-4] are supported with
208 * the exception of 543.0 for DG/UX tcpdump.
209 */
210 if (! ((hdr.version_major == PCAP_VERSION_MAJOR &&
211 hdr.version_minor <= PCAP_VERSION_MINOR) ||
212 (hdr.version_major == 543 &&
213 hdr.version_minor == 0))) {
214 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
215 "unsupported pcap savefile version %u.%u",
216 hdr.version_major, hdr.version_minor);
217 *err = 1;
218 return NULL;
219 }
220
221 /*
222 * OK, this is a good pcap file.
223 * Allocate a pcap_t for it.
224 */
225 p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
226 if (p == NULL) {
227 /* Allocation failed. */
228 *err = 1;
229 return (NULL);
230 }
231 p->swapped = swapped;
232 p->version_major = hdr.version_major;
233 p->version_minor = hdr.version_minor;
234 p->snapshot = hdr.snaplen;
235 if (p->snapshot <= 0) {
236 /*
237 * Bogus snapshot length; use the maximum for this
238 * link-layer type as a fallback.
239 *
240 * XXX - the only reason why snapshot is signed is
241 * that pcap_snapshot() returns an int, not an
242 * unsigned int.
243 */
244 p->snapshot = max_snaplen_for_dlt(hdr.linktype);
245 }
246 p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
247 p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
248
249 p->next_packet_op = pcap_next_packet;
250
251 ps = p->priv;
252
253 p->opt.tstamp_precision = precision;
254
255 /*
256 * Will we need to scale the timestamps to match what the
257 * user wants?
258 */
259 switch (precision) {
260
261 case PCAP_TSTAMP_PRECISION_MICRO:
262 if (magic == NSEC_TCPDUMP_MAGIC) {
263 /*
264 * The file has nanoseconds, the user
265 * wants microseconds; scale the
266 * precision down.
267 */
268 ps->scale_type = SCALE_DOWN;
269 } else {
270 /*
271 * The file has microseconds, the
272 * user wants microseconds; nothing to do.
273 */
274 ps->scale_type = PASS_THROUGH;
275 }
276 break;
277
278 case PCAP_TSTAMP_PRECISION_NANO:
279 if (magic == NSEC_TCPDUMP_MAGIC) {
280 /*
281 * The file has nanoseconds, the
282 * user wants nanoseconds; nothing to do.
283 */
284 ps->scale_type = PASS_THROUGH;
285 } else {
286 /*
287 * The file has microoseconds, the user
288 * wants nanoseconds; scale the
289 * precision up.
290 */
291 ps->scale_type = SCALE_UP;
292 }
293 break;
294
295 default:
296 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
297 "unknown time stamp resolution %u", precision);
298 free(p);
299 *err = 1;
300 return (NULL);
301 }
302
303 /*
304 * We interchanged the caplen and len fields at version 2.3,
305 * in order to match the bpf header layout. But unfortunately
306 * some files were written with version 2.3 in their headers
307 * but without the interchanged fields.
308 *
309 * In addition, DG/UX tcpdump writes out files with a version
310 * number of 543.0, and with the caplen and len fields in the
311 * pre-2.3 order.
312 */
313 switch (hdr.version_major) {
314
315 case 2:
316 if (hdr.version_minor < 3)
317 ps->lengths_swapped = SWAPPED;
318 else if (hdr.version_minor == 3)
319 ps->lengths_swapped = MAYBE_SWAPPED;
320 else
321 ps->lengths_swapped = NOT_SWAPPED;
322 break;
323
324 case 543:
325 ps->lengths_swapped = SWAPPED;
326 break;
327
328 default:
329 ps->lengths_swapped = NOT_SWAPPED;
330 break;
331 }
332
333 if (magic == KUZNETZOV_TCPDUMP_MAGIC) {
334 /*
335 * XXX - the patch that's in some versions of libpcap
336 * changes the packet header but not the magic number,
337 * and some other versions with this magic number have
338 * some extra debugging information in the packet header;
339 * we'd have to use some hacks^H^H^H^H^Hheuristics to
340 * detect those variants.
341 *
342 * Ethereal does that, but it does so by trying to read
343 * the first two packets of the file with each of the
344 * record header formats. That currently means it seeks
345 * backwards and retries the reads, which doesn't work
346 * on pipes. We want to be able to read from a pipe, so
347 * that strategy won't work; we'd have to buffer some
348 * data ourselves and read from that buffer in order to
349 * make that work.
350 */
351 ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
352
353 if (p->linktype == DLT_EN10MB) {
354 /*
355 * This capture might have been done in raw mode
356 * or cooked mode.
357 *
358 * If it was done in cooked mode, p->snapshot was
359 * passed to recvfrom() as the buffer size, meaning
360 * that the most packet data that would be copied
361 * would be p->snapshot. However, a faked Ethernet
362 * header would then have been added to it, so the
363 * most data that would be in a packet in the file
364 * would be p->snapshot + 14.
365 *
366 * We can't easily tell whether the capture was done
367 * in raw mode or cooked mode, so we'll assume it was
368 * cooked mode, and add 14 to the snapshot length.
369 * That means that, for a raw capture, the snapshot
370 * length will be misleading if you use it to figure
371 * out why a capture doesn't have all the packet data,
372 * but there's not much we can do to avoid that.
373 *
374 * But don't grow the snapshot length past the
375 * maximum value of an int.
376 */
377 if (p->snapshot <= INT_MAX - 14)
378 p->snapshot += 14;
379 else
380 p->snapshot = INT_MAX;
381 }
382 } else
383 ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
384
385 /*
386 * Allocate a buffer for the packet data.
387 * Choose the minimum of the file's snapshot length and 2K bytes;
388 * that should be enough for most network packets - we'll grow it
389 * if necessary. That way, we don't allocate a huge chunk of
390 * memory just because there's a huge snapshot length, as the
391 * snapshot length might be larger than the size of the largest
392 * packet.
393 */
394 p->bufsize = p->snapshot;
395 if (p->bufsize > 2048)
396 p->bufsize = 2048;
397 p->buffer = malloc(p->bufsize);
398 if (p->buffer == NULL) {
399 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
400 free(p);
401 *err = 1;
402 return (NULL);
403 }
404
405 p->cleanup_op = sf_cleanup;
406
407 return (p);
408 }
409
410 /*
411 * Grow the packet buffer to the specified size.
412 */
413 static int
414 grow_buffer(pcap_t *p, u_int bufsize)
415 {
416 void *bigger_buffer;
417
418 bigger_buffer = realloc(p->buffer, bufsize);
419 if (bigger_buffer == NULL) {
420 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
421 return (0);
422 }
423 p->buffer = bigger_buffer;
424 p->bufsize = bufsize;
425 return (1);
426 }
427
428 /*
429 * Read and return the next packet from the savefile. Return the header
430 * in hdr and a pointer to the contents in data. Return 0 on success, 1
431 * if there were no more packets, and -1 on an error.
432 */
433 static int
434 pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
435 {
436 struct pcap_sf *ps = p->priv;
437 struct pcap_sf_patched_pkthdr sf_hdr;
438 FILE *fp = p->rfile;
439 size_t amt_read;
440 bpf_u_int32 t;
441
442 /*
443 * Read the packet header; the structure we use as a buffer
444 * is the longer structure for files generated by the patched
445 * libpcap, but if the file has the magic number for an
446 * unpatched libpcap we only read as many bytes as the regular
447 * header has.
448 */
449 amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
450 if (amt_read != ps->hdrsize) {
451 if (ferror(fp)) {
452 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
453 errno, "error reading dump file");
454 return (-1);
455 } else {
456 if (amt_read != 0) {
457 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
458 "truncated dump file; tried to read %" PRIsize " header bytes, only got %" PRIsize,
459 ps->hdrsize, amt_read);
460 return (-1);
461 }
462 /* EOF */
463 return (1);
464 }
465 }
466
467 if (p->swapped) {
468 /* these were written in opposite byte order */
469 hdr->caplen = SWAPLONG(sf_hdr.caplen);
470 hdr->len = SWAPLONG(sf_hdr.len);
471 hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec);
472 hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec);
473 } else {
474 hdr->caplen = sf_hdr.caplen;
475 hdr->len = sf_hdr.len;
476 hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
477 hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
478 }
479
480 switch (ps->scale_type) {
481
482 case PASS_THROUGH:
483 /*
484 * Just pass the time stamp through.
485 */
486 break;
487
488 case SCALE_UP:
489 /*
490 * File has microseconds, user wants nanoseconds; convert
491 * it.
492 */
493 hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
494 break;
495
496 case SCALE_DOWN:
497 /*
498 * File has nanoseconds, user wants microseconds; convert
499 * it.
500 */
501 hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
502 break;
503 }
504
505 /* Swap the caplen and len fields, if necessary. */
506 switch (ps->lengths_swapped) {
507
508 case NOT_SWAPPED:
509 break;
510
511 case MAYBE_SWAPPED:
512 if (hdr->caplen <= hdr->len) {
513 /*
514 * The captured length is <= the actual length,
515 * so presumably they weren't swapped.
516 */
517 break;
518 }
519 /* FALLTHROUGH */
520
521 case SWAPPED:
522 t = hdr->caplen;
523 hdr->caplen = hdr->len;
524 hdr->len = t;
525 break;
526 }
527
528 /*
529 * Is the packet bigger than we consider sane?
530 */
531 if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) {
532 /*
533 * Yes. This may be a damaged or fuzzed file.
534 *
535 * Is it bigger than the snapshot length?
536 * (We don't treat that as an error if it's not
537 * bigger than the maximum we consider sane; see
538 * below.)
539 */
540 if (hdr->caplen > (bpf_u_int32)p->snapshot) {
541 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
542 "invalid packet capture length %u, bigger than "
543 "snaplen of %d", hdr->caplen, p->snapshot);
544 } else {
545 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
546 "invalid packet capture length %u, bigger than "
547 "maximum of %u", hdr->caplen,
548 max_snaplen_for_dlt(p->linktype));
549 }
550 return (-1);
551 }
552
553 if (hdr->caplen > (bpf_u_int32)p->snapshot) {
554 /*
555 * The packet is bigger than the snapshot length
556 * for this file.
557 *
558 * This can happen due to Solaris 2.3 systems tripping
559 * over the BUFMOD problem and not setting the snapshot
560 * length correctly in the savefile header.
561 *
562 * libpcap 0.4 and later on Solaris 2.3 should set the
563 * snapshot length correctly in the pcap file header,
564 * even though they don't set a snapshot length in bufmod
565 * (the buggy bufmod chops off the *beginning* of the
566 * packet if a snapshot length is specified); they should
567 * also reduce the captured length, as supplied to the
568 * per-packet callback, to the snapshot length if it's
569 * greater than the snapshot length, so the code using
570 * libpcap should see the packet cut off at the snapshot
571 * length, even though the full packet is copied up to
572 * userland.
573 *
574 * However, perhaps some versions of libpcap failed to
575 * set the snapshot length currectly in the file header
576 * or the per-packet header, or perhaps this is a
577 * corrupted safefile or a savefile built/modified by a
578 * fuzz tester, so we check anyway. We grow the buffer
579 * to be big enough for the snapshot length, read up
580 * to the snapshot length, discard the rest of the
581 * packet, and report the snapshot length as the captured
582 * length; we don't want to hand our caller a packet
583 * bigger than the snapshot length, because they might
584 * be assuming they'll never be handed such a packet,
585 * and might copy the packet into a snapshot-length-
586 * sized buffer, assuming it'll fit.
587 */
588 size_t bytes_to_discard;
589 size_t bytes_to_read, bytes_read;
590 char discard_buf[4096];
591
592 if (hdr->caplen > p->bufsize) {
593 /*
594 * Grow the buffer to the snapshot length.
595 */
596 if (!grow_buffer(p, p->snapshot))
597 return (-1);
598 }
599
600 /*
601 * Read the first p->snapshot bytes into the buffer.
602 */
603 amt_read = fread(p->buffer, 1, p->snapshot, fp);
604 if (amt_read != (bpf_u_int32)p->snapshot) {
605 if (ferror(fp)) {
606 pcap_fmt_errmsg_for_errno(p->errbuf,
607 PCAP_ERRBUF_SIZE, errno,
608 "error reading dump file");
609 } else {
610 /*
611 * Yes, this uses hdr->caplen; technically,
612 * it's true, because we would try to read
613 * and discard the rest of those bytes, and
614 * that would fail because we got EOF before
615 * the read finished.
616 */
617 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
618 "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
619 p->snapshot, amt_read);
620 }
621 return (-1);
622 }
623
624 /*
625 * Now read and discard what's left.
626 */
627 bytes_to_discard = hdr->caplen - p->snapshot;
628 bytes_read = amt_read;
629 while (bytes_to_discard != 0) {
630 bytes_to_read = bytes_to_discard;
631 if (bytes_to_read > sizeof (discard_buf))
632 bytes_to_read = sizeof (discard_buf);
633 amt_read = fread(discard_buf, 1, bytes_to_read, fp);
634 bytes_read += amt_read;
635 if (amt_read != bytes_to_read) {
636 if (ferror(fp)) {
637 pcap_fmt_errmsg_for_errno(p->errbuf,
638 PCAP_ERRBUF_SIZE, errno,
639 "error reading dump file");
640 } else {
641 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
642 "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
643 hdr->caplen, bytes_read);
644 }
645 return (-1);
646 }
647 bytes_to_discard -= amt_read;
648 }
649
650 /*
651 * Adjust caplen accordingly, so we don't get confused later
652 * as to how many bytes we have to play with.
653 */
654 hdr->caplen = p->snapshot;
655 } else {
656 /*
657 * The packet is within the snapshot length for this file.
658 */
659 if (hdr->caplen > p->bufsize) {
660 /*
661 * Grow the buffer to the next power of 2, or
662 * the snaplen, whichever is lower.
663 */
664 u_int new_bufsize;
665
666 new_bufsize = hdr->caplen;
667 /*
668 * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
669 */
670 new_bufsize--;
671 new_bufsize |= new_bufsize >> 1;
672 new_bufsize |= new_bufsize >> 2;
673 new_bufsize |= new_bufsize >> 4;
674 new_bufsize |= new_bufsize >> 8;
675 new_bufsize |= new_bufsize >> 16;
676 new_bufsize++;
677
678 if (new_bufsize > (u_int)p->snapshot)
679 new_bufsize = p->snapshot;
680
681 if (!grow_buffer(p, new_bufsize))
682 return (-1);
683 }
684
685 /* read the packet itself */
686 amt_read = fread(p->buffer, 1, hdr->caplen, fp);
687 if (amt_read != hdr->caplen) {
688 if (ferror(fp)) {
689 pcap_fmt_errmsg_for_errno(p->errbuf,
690 PCAP_ERRBUF_SIZE, errno,
691 "error reading dump file");
692 } else {
693 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
694 "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
695 hdr->caplen, amt_read);
696 }
697 return (-1);
698 }
699 }
700 *data = p->buffer;
701
702 if (p->swapped)
703 swap_pseudo_headers(p->linktype, hdr, *data);
704
705 return (0);
706 }
707
708 static int
709 sf_write_header(pcap_t *p, FILE *fp, int linktype, int snaplen)
710 {
711 struct pcap_file_header hdr;
712
713 hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
714 hdr.version_major = PCAP_VERSION_MAJOR;
715 hdr.version_minor = PCAP_VERSION_MINOR;
716
717 /*
718 * https://www.tcpdump.org/manpages/pcap-savefile.5.txt states:
719 * thiszone: 4-byte time zone offset; this is always 0.
720 * sigfigs: 4-byte number giving the accuracy of time stamps
721 * in the file; this is always 0.
722 */
723 hdr.thiszone = 0;
724 hdr.sigfigs = 0;
725 hdr.snaplen = snaplen;
726 hdr.linktype = linktype;
727
728 if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
729 return (-1);
730
731 return (0);
732 }
733
734 /*
735 * Output a packet to the initialized dump file.
736 */
737 void
738 pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
739 {
740 register FILE *f;
741 struct pcap_sf_pkthdr sf_hdr;
742
743 f = (FILE *)user;
744 /*
745 * Better not try writing pcap files after
746 * 2038-01-19 03:14:07 UTC; switch to pcapng.
747 */
748 sf_hdr.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
749 sf_hdr.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
750 sf_hdr.caplen = h->caplen;
751 sf_hdr.len = h->len;
752 /* XXX we should check the return status */
753 (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f);
754 (void)fwrite(sp, h->caplen, 1, f);
755 }
756
757 static pcap_dumper_t *
758 pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
759 {
760
761 #if defined(_WIN32) || defined(MSDOS)
762 /*
763 * If we're writing to the standard output, put it in binary
764 * mode, as savefiles are binary files.
765 *
766 * Otherwise, we turn off buffering.
767 * XXX - why? And why not on the standard output?
768 */
769 if (f == stdout)
770 SET_BINMODE(f);
771 else
772 setvbuf(f, NULL, _IONBF, 0);
773 #endif
774 if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
775 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
776 errno, "Can't write to %s", fname);
777 if (f != stdout)
778 (void)fclose(f);
779 return (NULL);
780 }
781 return ((pcap_dumper_t *)f);
782 }
783
784 /*
785 * Initialize so that sf_write() will output to the file named 'fname'.
786 */
787 pcap_dumper_t *
788 pcap_dump_open(pcap_t *p, const char *fname)
789 {
790 FILE *f;
791 int linktype;
792
793 /*
794 * If this pcap_t hasn't been activated, it doesn't have a
795 * link-layer type, so we can't use it.
796 */
797 if (!p->activated) {
798 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
799 "%s: not-yet-activated pcap_t passed to pcap_dump_open",
800 fname);
801 return (NULL);
802 }
803 linktype = dlt_to_linktype(p->linktype);
804 if (linktype == -1) {
805 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
806 "%s: link-layer type %d isn't supported in savefiles",
807 fname, p->linktype);
808 return (NULL);
809 }
810 linktype |= p->linktype_ext;
811
812 if (fname == NULL) {
813 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
814 "A null pointer was supplied as the file name");
815 return NULL;
816 }
817 if (fname[0] == '-' && fname[1] == '\0') {
818 f = stdout;
819 fname = "standard output";
820 } else {
821 /*
822 * "b" is supported as of C90, so *all* UN*Xes should
823 * support it, even though it does nothing. It's
824 * required on Windows, as the file is a binary file
825 * and must be written in binary mode.
826 */
827 f = fopen(fname, "wb");
828 if (f == NULL) {
829 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
830 errno, "%s", fname);
831 return (NULL);
832 }
833 }
834 return (pcap_setup_dump(p, linktype, f, fname));
835 }
836
837 /*
838 * Initialize so that sf_write() will output to the given stream.
839 */
840 pcap_dumper_t *
841 pcap_dump_fopen(pcap_t *p, FILE *f)
842 {
843 int linktype;
844
845 linktype = dlt_to_linktype(p->linktype);
846 if (linktype == -1) {
847 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
848 "stream: link-layer type %d isn't supported in savefiles",
849 p->linktype);
850 return (NULL);
851 }
852 linktype |= p->linktype_ext;
853
854 return (pcap_setup_dump(p, linktype, f, "stream"));
855 }
856
857 pcap_dumper_t *
858 pcap_dump_open_append(pcap_t *p, const char *fname)
859 {
860 FILE *f;
861 int linktype;
862 size_t amt_read;
863 struct pcap_file_header ph;
864
865 linktype = dlt_to_linktype(p->linktype);
866 if (linktype == -1) {
867 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
868 "%s: link-layer type %d isn't supported in savefiles",
869 fname, linktype);
870 return (NULL);
871 }
872
873 if (fname == NULL) {
874 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
875 "A null pointer was supplied as the file name");
876 return NULL;
877 }
878 if (fname[0] == '-' && fname[1] == '\0')
879 return (pcap_setup_dump(p, linktype, stdout, "standard output"));
880
881 /*
882 * "b" is supported as of C90, so *all* UN*Xes should support it,
883 * even though it does nothing. It's required on Windows, as the
884 * file is a binary file and must be read in binary mode.
885 */
886 f = fopen(fname, "rb+");
887 if (f == NULL) {
888 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
889 errno, "%s", fname);
890 return (NULL);
891 }
892
893 /*
894 * Try to read a pcap header.
895 */
896 amt_read = fread(&ph, 1, sizeof (ph), f);
897 if (amt_read != sizeof (ph)) {
898 if (ferror(f)) {
899 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
900 errno, "%s", fname);
901 fclose(f);
902 return (NULL);
903 } else if (feof(f) && amt_read > 0) {
904 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
905 "%s: truncated pcap file header", fname);
906 fclose(f);
907 return (NULL);
908 }
909 }
910
911 #if defined(_WIN32) || defined(MSDOS)
912 /*
913 * We turn off buffering.
914 * XXX - why? And why not on the standard output?
915 */
916 setvbuf(f, NULL, _IONBF, 0);
917 #endif
918
919 /*
920 * If a header is already present and:
921 *
922 * it's not for a pcap file of the appropriate resolution
923 * and the right byte order for this machine;
924 *
925 * the link-layer header types don't match;
926 *
927 * the snapshot lengths don't match;
928 *
929 * return an error.
930 */
931 if (amt_read > 0) {
932 /*
933 * A header is already present.
934 * Do the checks.
935 */
936 switch (ph.magic) {
937
938 case TCPDUMP_MAGIC:
939 if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
940 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
941 "%s: different time stamp precision, cannot append to file", fname);
942 fclose(f);
943 return (NULL);
944 }
945 break;
946
947 case NSEC_TCPDUMP_MAGIC:
948 if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
949 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
950 "%s: different time stamp precision, cannot append to file", fname);
951 fclose(f);
952 return (NULL);
953 }
954 break;
955
956 case SWAPLONG(TCPDUMP_MAGIC):
957 case SWAPLONG(NSEC_TCPDUMP_MAGIC):
958 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
959 "%s: different byte order, cannot append to file", fname);
960 fclose(f);
961 return (NULL);
962
963 case KUZNETZOV_TCPDUMP_MAGIC:
964 case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC):
965 case NAVTEL_TCPDUMP_MAGIC:
966 case SWAPLONG(NAVTEL_TCPDUMP_MAGIC):
967 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
968 "%s: not a pcap file to which we can append", fname);
969 fclose(f);
970 return (NULL);
971
972 default:
973 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
974 "%s: not a pcap file", fname);
975 fclose(f);
976 return (NULL);
977 }
978
979 /*
980 * Good version?
981 */
982 if (ph.version_major != PCAP_VERSION_MAJOR ||
983 ph.version_minor != PCAP_VERSION_MINOR) {
984 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
985 "%s: version is %u.%u, cannot append to file", fname,
986 ph.version_major, ph.version_minor);
987 fclose(f);
988 return (NULL);
989 }
990 if ((bpf_u_int32)linktype != ph.linktype) {
991 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
992 "%s: different linktype, cannot append to file", fname);
993 fclose(f);
994 return (NULL);
995 }
996 if ((bpf_u_int32)p->snapshot != ph.snaplen) {
997 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
998 "%s: different snaplen, cannot append to file", fname);
999 fclose(f);
1000 return (NULL);
1001 }
1002 } else {
1003 /*
1004 * A header isn't present; attempt to write it.
1005 */
1006 if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
1007 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1008 errno, "Can't write to %s", fname);
1009 (void)fclose(f);
1010 return (NULL);
1011 }
1012 }
1013
1014 /*
1015 * Start writing at the end of the file.
1016 */
1017 if (fseek(f, 0, SEEK_END) == -1) {
1018 pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
1019 errno, "Can't seek to end of %s", fname);
1020 (void)fclose(f);
1021 return (NULL);
1022 }
1023 return ((pcap_dumper_t *)f);
1024 }
1025
1026 FILE *
1027 pcap_dump_file(pcap_dumper_t *p)
1028 {
1029 return ((FILE *)p);
1030 }
1031
1032 long
1033 pcap_dump_ftell(pcap_dumper_t *p)
1034 {
1035 return (ftell((FILE *)p));
1036 }
1037
1038 #if defined(HAVE_FSEEKO)
1039 /*
1040 * We have fseeko(), so we have ftello().
1041 * If we have large file support (files larger than 2^31-1 bytes),
1042 * ftello() will give us a current file position with more than 32
1043 * bits.
1044 */
1045 int64_t
1046 pcap_dump_ftell64(pcap_dumper_t *p)
1047 {
1048 return (ftello((FILE *)p));
1049 }
1050 #elif defined(_MSC_VER)
1051 /*
1052 * We have Visual Studio; we support only 2005 and later, so we have
1053 * _ftelli64().
1054 */
1055 int64_t
1056 pcap_dump_ftell64(pcap_dumper_t *p)
1057 {
1058 return (_ftelli64((FILE *)p));
1059 }
1060 #else
1061 /*
1062 * We don't have ftello() or _ftelli64(), so fall back on ftell().
1063 * Either long is 64 bits, in which case ftell() should suffice,
1064 * or this is probably an older 32-bit UN*X without large file
1065 * support, which means you'll probably get errors trying to
1066 * write files > 2^31-1, so it won't matter anyway.
1067 *
1068 * XXX - what about MinGW?
1069 */
1070 int64_t
1071 pcap_dump_ftell64(pcap_dumper_t *p)
1072 {
1073 return (ftell((FILE *)p));
1074 }
1075 #endif
1076
1077 int
1078 pcap_dump_flush(pcap_dumper_t *p)
1079 {
1080
1081 if (fflush((FILE *)p) == EOF)
1082 return (-1);
1083 else
1084 return (0);
1085 }
1086
1087 void
1088 pcap_dump_close(pcap_dumper_t *p)
1089 {
1090
1091 #ifdef notyet
1092 if (ferror((FILE *)p))
1093 return-an-error;
1094 /* XXX should check return from fclose() too */
1095 #endif
1096 (void)fclose((FILE *)p);
1097 }