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