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